{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Importing Necessary Libraries\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "XIL5OCqJ7bh8"
   },
   "outputs": [],
   "source": [
    "# --- LangChain and LLM Imports ---\n",
    "from langchain_openai import ChatOpenAI \n",
    "from langchain_groq import ChatGroq\n",
    "\n",
    "# --- Document Loading and Vector Store ---\n",
    "from langchain.document_loaders import PyPDFLoader\n",
    "from langchain.vectorstores import FAISS\n",
    "from langchain.text_splitter import RecursiveCharacterTextSplitter\n",
    "from langchain.embeddings import OpenAIEmbeddings \n",
    "\n",
    "# --- Prompting and Document Utilities ---\n",
    "from langchain.prompts import PromptTemplate\n",
    "from langchain.docstore.document import Document\n",
    "from langchain.chains.summarize import load_summarize_chain\n",
    "\n",
    "# --- Core and Output Parsers ---\n",
    "from langchain_core.pydantic_v1 import BaseModel, Field\n",
    "from langchain_core.output_parsers import JsonOutputParser\n",
    "from langchain_core.runnables.graph import MermaidDrawMethod\n",
    "\n",
    "# --- LangGraph for Workflow Graphs ---\n",
    "from langgraph.graph import END, StateGraph\n",
    "\n",
    "# --- Standard Library Imports ---\n",
    "from time import monotonic\n",
    "from dotenv import load_dotenv\n",
    "from pprint import pprint\n",
    "import os\n",
    "\n",
    "# --- Datasets and Typing ---\n",
    "from datasets import Dataset\n",
    "from typing_extensions import TypedDict\n",
    "from IPython.display import display, Image\n",
    "from typing import List, TypedDict\n",
    "\n",
    "# --- RAGAS Metrics for Evaluation ---\n",
    "from ragas import evaluate\n",
    "from ragas.metrics import (\n",
    "    answer_correctness,\n",
    "    faithfulness,\n",
    "    answer_relevancy,\n",
    "    context_recall,\n",
    "    answer_similarity\n",
    ")\n",
    "\n",
    "import langgraph\n",
    "\n",
    "# --- Helper Functions ---\n",
    "from helper_functions import (\n",
    "    num_tokens_from_string,\n",
    "    replace_t_with_space,\n",
    "    replace_double_lines_with_one_line,\n",
    "    split_into_chapters,\n",
    "    analyse_metric_results,\n",
    "    escape_quotes,\n",
    "    text_wrap,\n",
    "    extract_book_quotes_as_documents\n",
    ")\n",
    "\n",
    "# --- Load environment variables (e.g., API keys) ---\n",
    "load_dotenv(override=True)\n",
    "\n",
    "# --- Set environment variable for debugging (optional) ---\n",
    "os.environ[\"PYDEVD_WARN_EVALUATION_TIMEOUT\"] = \"100000\""
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Setting OPENAI and GROQ API keys"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# --- Set API Keys for OpenAI and Groq ---\n",
    "\n",
    "# Set the OpenAI API key from environment variable (for use by OpenAI LLMs)\n",
    "os.environ[\"OPENAI_API_KEY\"] = os.getenv('OPENAI_API_KEY')\n",
    "\n",
    "# Retrieve the Groq API key from environment variable (for use by Groq LLMs)\n",
    "groq_api_key = os.getenv('GROQ_API_KEY')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Data preprocessing"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Defining Path to Harry Potter PDF\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "8mUYHG_S6y22"
   },
   "outputs": [],
   "source": [
    "# Define the path to the Harry Potter PDF file.\n",
    "# This variable will be used throughout the notebook for loading and processing the book.\n",
    "hp_pdf_path = \"Harry_Potter_Book_1_The_Sorcerers_Stone.pdf\""
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Splitting the PDF into Chapters and Preprocessing\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "cDHfDODdTIBY"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "17\n"
     ]
    }
   ],
   "source": [
    "# --- Split the PDF into chapters and preprocess the text ---\n",
    "\n",
    "# 1. Split the PDF into chapters using the provided helper function.\n",
    "#    This function takes the path to the PDF and returns a list of Document objects, each representing a chapter.\n",
    "chapters = split_into_chapters(hp_pdf_path)\n",
    "\n",
    "# 2. Clean up the text in each chapter by replacing unwanted characters (e.g., '\\t') with spaces.\n",
    "#    This ensures the text is consistent and easier to process downstream.\n",
    "chapters = replace_t_with_space(chapters)\n",
    "\n",
    "# 3. Print the number of chapters extracted to verify the result.\n",
    "print(len(chapters))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Creating a list of quotes taken from the book"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# --- Load and Preprocess the PDF, then Extract Quotes ---\n",
    "\n",
    "# 1. Load the PDF using PyPDFLoader\n",
    "loader = PyPDFLoader(hp_pdf_path)\n",
    "document = loader.load()\n",
    "\n",
    "# 2. Clean the loaded document by replacing unwanted characters (e.g., '\\t') with spaces\n",
    "document_cleaned = replace_t_with_space(document)\n",
    "\n",
    "# 3. Extract a list of quotes from the cleaned document as Document objects\n",
    "book_quotes_list = extract_book_quotes_as_documents(document_cleaned)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Defining Prompt Template for Summarization\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "49RqsAhDxjFg"
   },
   "outputs": [],
   "source": [
    "# --- Summarization Prompt Template for LLM-based Summarization ---\n",
    "\n",
    "# Define the template string for summarization.\n",
    "# This template instructs the language model to write an extensive summary of the provided text.\n",
    "summarization_prompt_template = \"\"\"Write an extensive summary of the following:\n",
    "\n",
    "{text}\n",
    "\n",
    "SUMMARY:\"\"\"\n",
    "\n",
    "# Create a PromptTemplate object using the template string.\n",
    "# The input variable \"text\" will be replaced with the content to summarize.\n",
    "summarization_prompt = PromptTemplate(\n",
    "    template=summarization_prompt_template,\n",
    "    input_variables=[\"text\"]\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Defining Function to Create Chapter Summaries using LLMs\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "ehe6iObnx4l9"
   },
   "outputs": [],
   "source": [
    "def create_chapter_summary(chapter):\n",
    "    \"\"\"\n",
    "    Creates a summary of a chapter using a large language model (LLM).\n",
    "\n",
    "    Args:\n",
    "        chapter: A Document object representing the chapter to summarize.\n",
    "\n",
    "    Returns:\n",
    "        A Document object containing the summary of the chapter.\n",
    "    \"\"\"\n",
    "\n",
    "    # Extract the text content from the chapter\n",
    "    chapter_txt = chapter.page_content\n",
    "\n",
    "    # Specify the LLM model and configuration\n",
    "    model_name = \"gpt-3.5-turbo-0125\"\n",
    "    llm = ChatOpenAI(temperature=0, model_name=model_name)\n",
    "    gpt_35_turbo_max_tokens = 16000  # Maximum token limit for the model\n",
    "    verbose = False  # Set to True for more detailed output\n",
    "\n",
    "    # Calculate the number of tokens in the chapter text\n",
    "    num_tokens = num_tokens_from_string(chapter_txt, model_name)\n",
    "\n",
    "    # Choose the summarization chain type based on token count\n",
    "    if num_tokens < gpt_35_turbo_max_tokens:\n",
    "        # For shorter chapters, use the \"stuff\" chain type\n",
    "        chain = load_summarize_chain(\n",
    "            llm,\n",
    "            chain_type=\"stuff\",\n",
    "            prompt=summarization_prompt,\n",
    "            verbose=verbose\n",
    "        )\n",
    "    else:\n",
    "        # For longer chapters, use the \"map_reduce\" chain type\n",
    "        chain = load_summarize_chain(\n",
    "            llm,\n",
    "            chain_type=\"map_reduce\",\n",
    "            map_prompt=summarization_prompt,\n",
    "            combine_prompt=summarization_prompt,\n",
    "            verbose=verbose\n",
    "        )\n",
    "\n",
    "    # Start timer to measure summarization time\n",
    "    start_time = monotonic()\n",
    "\n",
    "    # Create a Document object for the chapter\n",
    "    doc_chapter = Document(page_content=chapter_txt)\n",
    "\n",
    "    # Generate the summary using the selected chain\n",
    "    summary_result = chain.invoke([doc_chapter])\n",
    "\n",
    "    # Print chain type and execution time for reference\n",
    "    print(f\"Chain type: {chain.__class__.__name__}\")\n",
    "    print(f\"Run time: {monotonic() - start_time}\")\n",
    "\n",
    "    # Clean up the summary text (remove double newlines, etc.)\n",
    "    summary_text = replace_double_lines_with_one_line(summary_result[\"output_text\"])\n",
    "\n",
    "    # Create a Document object for the summary, preserving chapter metadata\n",
    "    doc_summary = Document(page_content=summary_text, metadata=chapter.metadata)\n",
    "\n",
    "    return doc_summary"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Generating Summaries for Each Chapter\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "id": "l4UBurLsMCHj",
    "outputId": "668932cf-02d8-446d-e0ed-3f85b30d3bba"
   },
   "outputs": [],
   "source": [
    "# --- Generate Summaries for Each Chapter ---\n",
    "\n",
    "# Initialize an empty list to store the summaries of each chapter\n",
    "chapter_summaries = []\n",
    "\n",
    "# Iterate over each chapter in the chapters list\n",
    "for chapter in chapters:\n",
    "    # Generate a summary for the current chapter using the create_chapter_summary function\n",
    "    summary = create_chapter_summary(chapter)\n",
    "    # Append the summary to the chapter_summaries list\n",
    "    chapter_summaries.append(summary)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Encoding the data"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Function to Encode a Book into a Vector Store using OpenAI Embeddings\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "9t1Kq6fGS0EA"
   },
   "outputs": [],
   "source": [
    "def encode_book(path, chunk_size=1000, chunk_overlap=200):\n",
    "    \"\"\"\n",
    "    Encodes a PDF book into a FAISS vector store using OpenAI embeddings.\n",
    "\n",
    "    Args:\n",
    "        path (str): The path to the PDF file.\n",
    "        chunk_size (int): The desired size of each text chunk.\n",
    "        chunk_overlap (int): The amount of overlap between consecutive chunks.\n",
    "\n",
    "    Returns:\n",
    "        FAISS: A FAISS vector store containing the encoded book content.\n",
    "    \"\"\"\n",
    "\n",
    "    # 1. Load the PDF document using PyPDFLoader\n",
    "    loader = PyPDFLoader(path)\n",
    "    documents = loader.load()\n",
    "\n",
    "    # 2. Split the document into chunks for embedding\n",
    "    text_splitter = RecursiveCharacterTextSplitter(\n",
    "        chunk_size=chunk_size,\n",
    "        chunk_overlap=chunk_overlap,\n",
    "        length_function=len\n",
    "    )\n",
    "    texts = text_splitter.split_documents(documents)\n",
    "\n",
    "    # 3. Clean up the text chunks (replace unwanted characters)\n",
    "    cleaned_texts = replace_t_with_space(texts)\n",
    "\n",
    "    # 4. Create OpenAI embeddings and encode the cleaned text chunks into a FAISS vector store\n",
    "    embeddings = OpenAIEmbeddings()\n",
    "    vectorstore = FAISS.from_documents(cleaned_texts, embeddings)\n",
    "\n",
    "    # 5. Return the vector store\n",
    "    return vectorstore"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Encoding Chapter Summaries into Vector Store\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "FHt9Y12gMp2z"
   },
   "outputs": [],
   "source": [
    "def encode_chapter_summaries(chapter_summaries):\n",
    "    \"\"\"\n",
    "    Encodes a list of chapter summaries into a FAISS vector store using OpenAI embeddings.\n",
    "\n",
    "    Args:\n",
    "        chapter_summaries (list): A list of Document objects representing the chapter summaries.\n",
    "\n",
    "    Returns:\n",
    "        FAISS: A FAISS vector store containing the encoded chapter summaries.\n",
    "    \"\"\"\n",
    "    # Create OpenAI embeddings instance\n",
    "    embeddings = OpenAIEmbeddings()\n",
    "    \n",
    "    # Encode the chapter summaries into a FAISS vector store\n",
    "    chapter_summaries_vectorstore = FAISS.from_documents(chapter_summaries, embeddings)\n",
    "    \n",
    "    # Return the vector store\n",
    "    return chapter_summaries_vectorstore"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Encoding Quotes into Vector Store"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "def encode_quotes(book_quotes_list):\n",
    "    \"\"\"\n",
    "    Encodes a list of book quotes into a FAISS vector store using OpenAI embeddings.\n",
    "\n",
    "    Args:\n",
    "        book_quotes_list (list): A list of Document objects, each representing a quote from the book.\n",
    "\n",
    "    Returns:\n",
    "        FAISS: A FAISS vector store containing the encoded book quotes.\n",
    "    \"\"\"\n",
    "    # Create OpenAI embeddings instance\n",
    "    embeddings = OpenAIEmbeddings()\n",
    "    \n",
    "    # Encode the book quotes into a FAISS vector store\n",
    "    quotes_vectorstore = FAISS.from_documents(book_quotes_list, embeddings)\n",
    "    \n",
    "    # Return the vector store\n",
    "    return quotes_vectorstore"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Creating vector stores and retrievers "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Creating Vector Stores and Retrievers for Book and Chapter Summaries\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# --- Create or Load Vector Stores for Book Chunks, Chapter Summaries, and Book Quotes ---\n",
    "\n",
    "# Check if the vector stores already exist on disk\n",
    "if (\n",
    "    os.path.exists(\"chunks_vector_store\") and\n",
    "    os.path.exists(\"chapter_summaries_vector_store\") and\n",
    "    os.path.exists(\"book_quotes_vectorstore\")\n",
    "):\n",
    "    # If vector stores exist, load them using OpenAI embeddings\n",
    "    embeddings = OpenAIEmbeddings()\n",
    "    chunks_vector_store = FAISS.load_local(\n",
    "        \"chunks_vector_store\", embeddings, allow_dangerous_deserialization=True\n",
    "    )\n",
    "    chapter_summaries_vector_store = FAISS.load_local(\n",
    "        \"chapter_summaries_vector_store\", embeddings, allow_dangerous_deserialization=True\n",
    "    )\n",
    "    book_quotes_vectorstore = FAISS.load_local(\n",
    "        \"book_quotes_vectorstore\", embeddings, allow_dangerous_deserialization=True\n",
    "    )\n",
    "else:\n",
    "    # If vector stores do not exist, encode and save them\n",
    "\n",
    "    # 1. Encode the book into a vector store of chunks\n",
    "    chunks_vector_store = encode_book(hp_pdf_path, chunk_size=1000, chunk_overlap=200)\n",
    "\n",
    "    # 2. Encode the chapter summaries into a vector store\n",
    "    chapter_summaries_vector_store = encode_chapter_summaries(chapter_summaries)\n",
    "\n",
    "    # 3. Encode the book quotes into a vector store\n",
    "    book_quotes_vectorstore = encode_quotes(book_quotes_list)\n",
    "\n",
    "    # 4. Save the vector stores to disk for future use\n",
    "    chunks_vector_store.save_local(\"chunks_vector_store\")\n",
    "    chapter_summaries_vector_store.save_local(\"chapter_summaries_vector_store\")\n",
    "    book_quotes_vectorstore.save_local(\"book_quotes_vectorstore\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Create retrievers from the vector stores"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# --- Create Query Retrievers from Vector Stores ---\n",
    "\n",
    "# The following retrievers are used to fetch relevant documents from the vector stores\n",
    "# based on a query. The number of results returned can be controlled via the 'k' parameter.\n",
    "\n",
    "# Retriever for book chunks (returns the top 1 most relevant chunk)\n",
    "chunks_query_retriever = chunks_vector_store.as_retriever(search_kwargs={\"k\": 1})\n",
    "\n",
    "# Retriever for chapter summaries (returns the top 1 most relevant summary)\n",
    "chapter_summaries_query_retriever = chapter_summaries_vector_store.as_retriever(search_kwargs={\"k\": 1})\n",
    "\n",
    "# Retriever for book quotes (returns the top 10 most relevant quotes)\n",
    "book_quotes_query_retriever = book_quotes_vectorstore.as_retriever(search_kwargs={\"k\": 10})"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# For advanced RAGing\n",
    "## For questions that can be answered by retrieval based on the original query, we create a `langgraph` graph for answering the query.\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Agrregate retrieved content as string context"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "def retrieve_context_per_question(state):\n",
    "    \"\"\"\n",
    "    Retrieves relevant context for a given question by aggregating content from:\n",
    "    - Book chunks\n",
    "    - Chapter summaries\n",
    "    - Book quotes\n",
    "\n",
    "    Args:\n",
    "        state (dict): A dictionary containing the question to answer, with key \"question\".\n",
    "\n",
    "    Returns:\n",
    "        dict: A dictionary with keys:\n",
    "            - \"context\": Aggregated context string from all sources.\n",
    "            - \"question\": The original question.\n",
    "    \"\"\"\n",
    "    question = state[\"question\"]\n",
    "\n",
    "    # Retrieve relevant book chunks\n",
    "    print(\"Retrieving relevant chunks...\")\n",
    "    docs = chunks_query_retriever.get_relevant_documents(question)\n",
    "    context = \" \".join(doc.page_content for doc in docs)\n",
    "\n",
    "    # Retrieve relevant chapter summaries\n",
    "    print(\"Retrieving relevant chapter summaries...\")\n",
    "    docs_summaries = chapter_summaries_query_retriever.get_relevant_documents(question)\n",
    "    context_summaries = \" \".join(\n",
    "        f\"{doc.page_content} (Chapter {doc.metadata['chapter']})\" for doc in docs_summaries\n",
    "    )\n",
    "\n",
    "    # Retrieve relevant book quotes\n",
    "    print(\"Retrieving relevant book quotes...\")\n",
    "    docs_book_quotes = book_quotes_query_retriever.get_relevant_documents(question)\n",
    "    book_quotes = \" \".join(doc.page_content for doc in docs_book_quotes)\n",
    "\n",
    "    # Aggregate all contexts and escape problematic characters\n",
    "    all_contexts = context + context_summaries + book_quotes\n",
    "    all_contexts = escape_quotes(all_contexts)\n",
    "\n",
    "    return {\"context\": all_contexts, \"question\": question}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### LLM based function to distill only relevant retrieved content"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# --- LLM-based Function to Filter Only Relevant Retrieved Content ---\n",
    "\n",
    "# Prompt template for filtering relevant content from retrieved documents\n",
    "keep_only_relevant_content_prompt_template = \"\"\"\n",
    "You receive a query: {query} and retrieved documents: {retrieved_documents} from a vector store.\n",
    "You need to filter out all the non relevant information that doesn't supply important information regarding the {query}.\n",
    "Your goal is just to filter out the non relevant information.\n",
    "You can remove parts of sentences that are not relevant to the query or remove whole sentences that are not relevant to the query.\n",
    "DO NOT ADD ANY NEW INFORMATION THAT IS NOT IN THE RETRIEVED DOCUMENTS.\n",
    "Output the filtered relevant content.\n",
    "\"\"\"\n",
    "\n",
    "# Output schema for the filtered relevant content\n",
    "class KeepRelevantContent(BaseModel):\n",
    "    relevant_content: str = Field(\n",
    "        description=\"The relevant content from the retrieved documents that is relevant to the query.\"\n",
    "    )\n",
    "\n",
    "# Create the prompt for the LLM\n",
    "keep_only_relevant_content_prompt = PromptTemplate(\n",
    "    template=keep_only_relevant_content_prompt_template,\n",
    "    input_variables=[\"query\", \"retrieved_documents\"],\n",
    ")\n",
    "\n",
    "# Initialize the LLM for filtering relevant content\n",
    "keep_only_relevant_content_llm = ChatOpenAI(\n",
    "    temperature=0, model_name=\"gpt-4o\", max_tokens=2000\n",
    ")\n",
    "\n",
    "# Create the LLM chain for filtering relevant content\n",
    "keep_only_relevant_content_chain = (\n",
    "    keep_only_relevant_content_prompt\n",
    "    | keep_only_relevant_content_llm.with_structured_output(KeepRelevantContent)\n",
    ")\n",
    "\n",
    "def keep_only_relevant_content(state):\n",
    "    \"\"\"\n",
    "    Filters and keeps only the relevant content from the retrieved documents that is relevant to the query.\n",
    "\n",
    "    Args:\n",
    "        state (dict): A dictionary containing:\n",
    "            - \"question\": The query question.\n",
    "            - \"context\": The retrieved documents as a string.\n",
    "\n",
    "    Returns:\n",
    "        dict: A dictionary containing:\n",
    "            - \"relevant_context\": The filtered relevant content.\n",
    "            - \"context\": The original context.\n",
    "            - \"question\": The original question.\n",
    "    \"\"\"\n",
    "    question = state[\"question\"]\n",
    "    context = state[\"context\"]\n",
    "\n",
    "    input_data = {\n",
    "        \"query\": question,\n",
    "        \"retrieved_documents\": context\n",
    "    }\n",
    "\n",
    "    print(\"Keeping only the relevant content...\")\n",
    "    pprint(\"--------------------\")\n",
    "    output = keep_only_relevant_content_chain.invoke(input_data)\n",
    "    relevant_content = output.relevant_content\n",
    "    relevant_content = \"\".join(relevant_content)\n",
    "    relevant_content = escape_quotes(relevant_content)\n",
    "\n",
    "    return {\n",
    "        \"relevant_context\": relevant_content,\n",
    "        \"context\": context,\n",
    "        \"question\": question\n",
    "    }"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### LLM based function to re-write a question"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# --- LLM-based Function to Rewrite a Question for Better Vectorstore Retrieval ---\n",
    "\n",
    "class RewriteQuestion(BaseModel):\n",
    "    \"\"\"\n",
    "    Output schema for the rewritten question.\n",
    "    \"\"\"\n",
    "    rewritten_question: str = Field(\n",
    "        description=\"The improved question optimized for vectorstore retrieval.\"\n",
    "    )\n",
    "    explanation: str = Field(\n",
    "        description=\"The explanation of the rewritten question.\"\n",
    "    )\n",
    "\n",
    "# Create a JSON parser for the output schema\n",
    "rewrite_question_string_parser = JsonOutputParser(pydantic_object=RewriteQuestion)\n",
    "\n",
    "# Initialize the LLM for rewriting questions\n",
    "rewrite_llm = ChatGroq(\n",
    "    temperature=0,\n",
    "    model_name=\"llama3-70b-8192\",\n",
    "    groq_api_key=groq_api_key,\n",
    "    max_tokens=4000\n",
    ")\n",
    "\n",
    "# Define the prompt template for question rewriting\n",
    "rewrite_prompt_template = \"\"\"\n",
    "You are a question re-writer that converts an input question to a better version optimized for vectorstore retrieval.\n",
    "Analyze the input question {question} and try to reason about the underlying semantic intent / meaning.\n",
    "{format_instructions}\n",
    "\"\"\"\n",
    "\n",
    "# Create the prompt object\n",
    "rewrite_prompt = PromptTemplate(\n",
    "    template=rewrite_prompt_template,\n",
    "    input_variables=[\"question\"],\n",
    "    partial_variables={\"format_instructions\": rewrite_question_string_parser.get_format_instructions()},\n",
    ")\n",
    "\n",
    "# Combine prompt, LLM, and parser into a chain\n",
    "question_rewriter = rewrite_prompt | rewrite_llm | rewrite_question_string_parser\n",
    "\n",
    "def rewrite_question(state):\n",
    "    \"\"\"\n",
    "    Rewrites the given question using the LLM to optimize it for vectorstore retrieval.\n",
    "\n",
    "    Args:\n",
    "        state (dict): A dictionary containing the question to rewrite, with key \"question\".\n",
    "\n",
    "    Returns:\n",
    "        dict: A dictionary with the rewritten question under the key \"question\".\n",
    "    \"\"\"\n",
    "    question = state[\"question\"]\n",
    "    print(\"Rewriting the question...\")\n",
    "    result = question_rewriter.invoke({\"question\": question})\n",
    "    new_question = result[\"rewritten_question\"]\n",
    "    return {\"question\": new_question}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### LLM based function to answer a question given context, using Chain of Thought"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# --- LLM-based Function to Answer a Question from Context Using Chain-of-Thought Reasoning ---\n",
    "\n",
    "# Define the output schema for the answer\n",
    "class QuestionAnswerFromContext(BaseModel):\n",
    "    answer_based_on_content: str = Field(\n",
    "        description=\"Generates an answer to a query based on a given context.\"\n",
    "    )\n",
    "\n",
    "# Initialize the LLM for answering questions with chain-of-thought reasoning\n",
    "question_answer_from_context_llm = ChatOpenAI(\n",
    "    temperature=0,\n",
    "    model_name=\"gpt-4o\",\n",
    "    max_tokens=2000\n",
    ")\n",
    "\n",
    "# Define the prompt template with chain-of-thought examples and instructions\n",
    "question_answer_cot_prompt_template = \"\"\" \n",
    "Examples of Chain-of-Thought Reasoning\n",
    "\n",
    "Example 1\n",
    "\n",
    "Context: Mary is taller than Jane. Jane is shorter than Tom. Tom is the same height as David.\n",
    "Question: Who is the tallest person?\n",
    "Reasoning Chain:\n",
    "The context tells us Mary is taller than Jane\n",
    "It also says Jane is shorter than Tom\n",
    "And Tom is the same height as David\n",
    "So the order from tallest to shortest is: Mary, Tom/David, Jane\n",
    "Therefore, Mary must be the tallest person\n",
    "\n",
    "Example 2\n",
    "Context: Harry was reading a book about magic spells. One spell allowed the caster to turn a person into an animal for a short time. Another spell could levitate objects.\n",
    " A third spell created a bright light at the end of the caster's wand.\n",
    "Question: Based on the context, if Harry cast these spells, what could he do?\n",
    "Reasoning Chain:\n",
    "The context describes three different magic spells\n",
    "The first spell allows turning a person into an animal temporarily\n",
    "The second spell can levitate or float objects\n",
    "The third spell creates a bright light\n",
    "If Harry cast these spells, he could turn someone into an animal for a while, make objects float, and create a bright light source\n",
    "So based on the context, if Harry cast these spells he could transform people, levitate things, and illuminate an area\n",
    "Instructions.\n",
    "\n",
    "Example 3 \n",
    "Context: Harry Potter woke up on his birthday to find a present at the end of his bed. He excitedly opened it to reveal a Nimbus 2000 broomstick.\n",
    "Question: Why did Harry receive a broomstick for his birthday?\n",
    "Reasoning Chain:\n",
    "The context states that Harry Potter woke up on his birthday and received a present - a Nimbus 2000 broomstick.\n",
    "However, the context does not provide any information about why he received that specific present or who gave it to him.\n",
    "There are no details about Harry's interests, hobbies, or the person who gifted him the broomstick.\n",
    "Without any additional context about Harry's background or the gift-giver's motivations, there is no way to determine the reason he received a broomstick as a birthday present.\n",
    "\n",
    "For the question below, provide your answer by first showing your step-by-step reasoning process, breaking down the problem into a chain of thought before arriving at the final answer,\n",
    " just like in the previous examples.\n",
    "Context\n",
    "{context}\n",
    "Question\n",
    "{question}\n",
    "\"\"\"\n",
    "\n",
    "# Create the prompt object\n",
    "question_answer_from_context_cot_prompt = PromptTemplate(\n",
    "    template=question_answer_cot_prompt_template,\n",
    "    input_variables=[\"context\", \"question\"],\n",
    ")\n",
    "\n",
    "# Combine the prompt and LLM into a chain with structured output\n",
    "question_answer_from_context_cot_chain = (\n",
    "    question_answer_from_context_cot_prompt\n",
    "    | question_answer_from_context_llm.with_structured_output(QuestionAnswerFromContext)\n",
    ")\n",
    "\n",
    "def answer_question_from_context(state):\n",
    "    \"\"\"\n",
    "    Answers a question from a given context using chain-of-thought reasoning.\n",
    "\n",
    "    Args:\n",
    "        state (dict): A dictionary containing:\n",
    "            - \"question\": The query question.\n",
    "            - \"context\" or \"aggregated_context\": The context to answer the question from.\n",
    "\n",
    "    Returns:\n",
    "        dict: A dictionary containing:\n",
    "            - \"answer\": The answer to the question from the context.\n",
    "            - \"context\": The context used.\n",
    "            - \"question\": The original question.\n",
    "    \"\"\"\n",
    "    # Use 'aggregated_context' if available, otherwise fall back to 'context'\n",
    "    question = state[\"question\"]\n",
    "    context = state[\"aggregated_context\"] if \"aggregated_context\" in state else state[\"context\"]\n",
    "\n",
    "    input_data = {\n",
    "        \"question\": question,\n",
    "        \"context\": context\n",
    "    }\n",
    "\n",
    "    print(\"Answering the question from the retrieved context...\")\n",
    "\n",
    "    # Invoke the LLM chain to get the answer\n",
    "    output = question_answer_from_context_cot_chain.invoke(input_data)\n",
    "    answer = output.answer_based_on_content\n",
    "    print(f'answer before checking hallucination: {answer}')\n",
    "\n",
    "    return {\n",
    "        \"answer\": answer,\n",
    "        \"context\": context,\n",
    "        \"question\": question\n",
    "    }"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Create graph edges"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### LLM based function to determine if retrieved content is relevant to the question"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# --- LLM-based Function to Determine Relevance of Retrieved Content ---\n",
    "\n",
    "# Prompt template for checking if the retrieved context is relevant to the query\n",
    "is_relevant_content_prompt_template = \"\"\"\n",
    "You receive a query: {query} and a context: {context} retrieved from a vector store. \n",
    "You need to determine if the document is relevant to the query. \n",
    "{format_instructions}\n",
    "\"\"\"\n",
    "\n",
    "# Output schema for the relevance check\n",
    "class Relevance(BaseModel):\n",
    "    is_relevant: bool = Field(description=\"Whether the document is relevant to the query.\")\n",
    "    explanation: str = Field(description=\"An explanation of why the document is relevant or not.\")\n",
    "\n",
    "# JSON parser for the output schema\n",
    "is_relevant_json_parser = JsonOutputParser(pydantic_object=Relevance)\n",
    "\n",
    "# Initialize the LLM for relevance checking\n",
    "is_relevant_llm = ChatGroq(\n",
    "    temperature=0,\n",
    "    model_name=\"llama3-70b-8192\",\n",
    "    groq_api_key=groq_api_key,\n",
    "    max_tokens=4000\n",
    ")\n",
    "\n",
    "# Create the prompt object for the LLM\n",
    "is_relevant_content_prompt = PromptTemplate(\n",
    "    template=is_relevant_content_prompt_template,\n",
    "    input_variables=[\"query\", \"context\"],\n",
    "    partial_variables={\"format_instructions\": is_relevant_json_parser.get_format_instructions()},\n",
    ")\n",
    "\n",
    "# Combine prompt, LLM, and parser into a chain\n",
    "is_relevant_content_chain = is_relevant_content_prompt | is_relevant_llm | is_relevant_json_parser\n",
    "\n",
    "def is_relevant_content(state):\n",
    "    \"\"\"\n",
    "    Determines if the retrieved context is relevant to the query.\n",
    "\n",
    "    Args:\n",
    "        state (dict): A dictionary containing:\n",
    "            - \"question\": The query question.\n",
    "            - \"context\": The retrieved context to check for relevance.\n",
    "\n",
    "    Returns:\n",
    "        str: \"relevant\" if the context is relevant, \"not relevant\" otherwise.\n",
    "    \"\"\"\n",
    "    question = state[\"question\"]\n",
    "    context = state[\"context\"]\n",
    "\n",
    "    input_data = {\n",
    "        \"query\": question,\n",
    "        \"context\": context\n",
    "    }\n",
    "\n",
    "    # Invoke the LLM chain to determine if the document is relevant\n",
    "    output = is_relevant_content_chain.invoke(input_data)\n",
    "    print(\"Determining if the document is relevant...\")\n",
    "    if output[\"is_relevant\"]:\n",
    "        print(\"The document is relevant.\")\n",
    "        return \"relevant\"\n",
    "    else:\n",
    "        print(\"The document is not relevant.\")\n",
    "        return \"not relevant\""
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### LLM chain to check if an answer is a hallucination or grounded on facts"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# --- LLM Chain to Check if an Answer is Grounded in the Provided Context ---\n",
    "\n",
    "# Define the output schema for the grounding check\n",
    "class IsGroundedOnFacts(BaseModel):\n",
    "    \"\"\"\n",
    "    Output schema for checking if the answer is grounded in the provided context.\n",
    "    \"\"\"\n",
    "    grounded_on_facts: bool = Field(description=\"Answer is grounded in the facts, 'yes' or 'no'\")\n",
    "\n",
    "# Initialize the LLM for fact-checking (using GPT-4o)\n",
    "is_grounded_on_facts_llm = ChatOpenAI(\n",
    "    temperature=0,\n",
    "    model_name=\"gpt-4o\",\n",
    "    max_tokens=2000\n",
    ")\n",
    "\n",
    "# Define the prompt template for fact-checking\n",
    "is_grounded_on_facts_prompt_template = \"\"\"\n",
    "You are a fact-checker that determines if the given answer {answer} is grounded in the given context {context}\n",
    "You don't mind if it doesn't make sense, as long as it is grounded in the context.\n",
    "Output a JSON containing the answer to the question, and apart from the JSON format don't output any additional text.\n",
    "\"\"\"\n",
    "\n",
    "# Create the prompt object\n",
    "is_grounded_on_facts_prompt = PromptTemplate(\n",
    "    template=is_grounded_on_facts_prompt_template,\n",
    "    input_variables=[\"context\", \"answer\"],\n",
    ")\n",
    "\n",
    "# Create the LLM chain for fact-checking\n",
    "is_grounded_on_facts_chain = (\n",
    "    is_grounded_on_facts_prompt\n",
    "    | is_grounded_on_facts_llm.with_structured_output(IsGroundedOnFacts)\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### LLM chain to determine if a question can be fully answered given a context"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# --- LLM Chain to Determine if a Question Can Be Fully Answered from Context ---\n",
    "\n",
    "# Define the prompt template for the LLM\n",
    "can_be_answered_prompt_template = \"\"\"\n",
    "You receive a query: {question} and a context: {context}. \n",
    "You need to determine if the question can be fully answered based on the context.\n",
    "{format_instructions}\n",
    "\"\"\"\n",
    "\n",
    "# Define the output schema for the LLM's response\n",
    "class QuestionAnswer(BaseModel):\n",
    "    can_be_answered: bool = Field(\n",
    "        description=\"binary result of whether the question can be fully answered or not\"\n",
    "    )\n",
    "    explanation: str = Field(\n",
    "        description=\"An explanation of why the question can be fully answered or not.\"\n",
    "    )\n",
    "\n",
    "# Create a JSON parser for the output schema\n",
    "can_be_answered_json_parser = JsonOutputParser(pydantic_object=QuestionAnswer)\n",
    "\n",
    "# Create the prompt object for the LLM\n",
    "answer_question_prompt = PromptTemplate(\n",
    "    template=can_be_answered_prompt_template,\n",
    "    input_variables=[\"question\", \"context\"],\n",
    "    partial_variables={\"format_instructions\": can_be_answered_json_parser.get_format_instructions()},\n",
    ")\n",
    "\n",
    "# Initialize the LLM (Groq Llama3) for this task\n",
    "can_be_answered_llm = ChatGroq(\n",
    "    temperature=0,\n",
    "    model_name=\"llama3-70b-8192\",\n",
    "    groq_api_key=groq_api_key,\n",
    "    max_tokens=4000\n",
    ")\n",
    "\n",
    "# Compose the chain: prompt -> LLM -> output parser\n",
    "can_be_answered_chain = answer_question_prompt | can_be_answered_llm | can_be_answered_json_parser"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### function to check both cases - hallucination and full answer"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "def grade_generation_v_documents_and_question(state):\n",
    "    \"\"\"\n",
    "    Grades the generated answer to a question based on:\n",
    "    - Whether the answer is grounded in the provided context (fact-checking)\n",
    "    - Whether the question can be fully answered from the context\n",
    "\n",
    "    Args:\n",
    "        state (dict): A dictionary containing:\n",
    "            - \"context\": The context used to answer the question\n",
    "            - \"question\": The original question\n",
    "            - \"answer\": The generated answer\n",
    "\n",
    "    Returns:\n",
    "        str: One of \"hallucination\", \"useful\", or \"not_useful\"\n",
    "    \"\"\"\n",
    "\n",
    "    # Extract relevant fields from state\n",
    "    context = state[\"context\"]\n",
    "    answer = state[\"answer\"]\n",
    "    question = state[\"question\"]\n",
    "\n",
    "    # 1. Check if the answer is grounded in the provided context (fact-checking)\n",
    "    print(\"Checking if the answer is grounded in the facts...\")\n",
    "    result = is_grounded_on_facts_chain.invoke({\"context\": context, \"answer\": answer})\n",
    "    grounded_on_facts = result.grounded_on_facts\n",
    "\n",
    "    if not grounded_on_facts:\n",
    "        # If not grounded, label as hallucination\n",
    "        print(\"The answer is hallucination.\")\n",
    "        return \"hallucination\"\n",
    "    else:\n",
    "        print(\"The answer is grounded in the facts.\")\n",
    "\n",
    "        # 2. Check if the question can be fully answered from the context\n",
    "        input_data = {\n",
    "            \"question\": question,\n",
    "            \"context\": context\n",
    "        }\n",
    "        print(\"Determining if the question is fully answered...\")\n",
    "        output = can_be_answered_chain.invoke(input_data)\n",
    "        can_be_answered = output[\"can_be_answered\"]\n",
    "\n",
    "        if can_be_answered:\n",
    "            print(\"The question can be fully answered.\")\n",
    "            return \"useful\"\n",
    "        else:\n",
    "            print(\"The question cannot be fully answered.\")\n",
    "            return \"not_useful\""
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Test a pipeline of all parts"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Retrieving relevant chunks...\n",
      "Retrieving relevant chapter summaries...\n",
      "keeping only the relevant content...\n",
      "'--------------------'\n",
      "Determining if the document is relevant...\n",
      "The document is relevant.\n",
      "Answering the question from the retrieved context...\n",
      "answer before checking hallucination: Fluffy is a three-headed dog.\n",
      "Checking if the answer is grounded in the facts...\n",
      "The answer is grounded in the facts.\n",
      "Determining if the question is fully answered...\n",
      "The question can be fully answered.\n",
      "Fluffy is a three-headed dog.\n"
     ]
    }
   ],
   "source": [
    "# --- Step-by-step Pipeline for Answering a Question with RAG and LLMs ---\n",
    "\n",
    "# 1. Define the initial state with the question to answer\n",
    "init_state = {\"question\": \"who is fluffy?\"}\n",
    "\n",
    "# 2. Retrieve relevant context for the question from the vector stores (chunks, summaries, quotes)\n",
    "context_state = retrieve_context_per_question(init_state)\n",
    "\n",
    "# 3. Use an LLM to filter and keep only the content relevant to the question from the retrieved context\n",
    "relevant_content_state = keep_only_relevant_content(context_state)\n",
    "\n",
    "# 4. Check if the filtered content is relevant to the question using an LLM-based relevance check\n",
    "is_relevant_content_state = is_relevant_content(relevant_content_state)\n",
    "\n",
    "# 5. Use an LLM to answer the question based on the relevant context\n",
    "answer_state = answer_question_from_context(relevant_content_state)\n",
    "\n",
    "# 6. Grade the generated answer:\n",
    "#    - Check if the answer is grounded in the provided context (fact-checking)\n",
    "#    - Check if the question can be fully answered from the context\n",
    "final_answer = grade_generation_v_documents_and_question(answer_state)\n",
    "\n",
    "# 7. Print the final answer\n",
    "print(answer_state[\"answer\"])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Build the Graph"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/jpeg": "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",
      "text/plain": [
       "<IPython.core.display.Image object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# -----------------------------------------------\n",
    "# Qualitative Retrieval Answer Graph Construction\n",
    "# -----------------------------------------------\n",
    "\n",
    "# Define the state for the workflow graph\n",
    "class QualitativeRetievalAnswerGraphState(TypedDict):\n",
    "    question: str\n",
    "    context: str\n",
    "    answer: str\n",
    "\n",
    "# Create the workflow graph object\n",
    "qualitative_retrieval_answer_workflow = StateGraph(QualitativeRetievalAnswerGraphState)\n",
    "\n",
    "# -------------------------\n",
    "# Define and Add Graph Nodes\n",
    "# -------------------------\n",
    "# Each node represents a function in the pipeline\n",
    "\n",
    "# Node: Retrieve context for the question from vector stores\n",
    "qualitative_retrieval_answer_workflow.add_node(\n",
    "    \"retrieve_context_per_question\", retrieve_context_per_question\n",
    ")\n",
    "\n",
    "# Node: Use LLM to keep only relevant content from the retrieved context\n",
    "qualitative_retrieval_answer_workflow.add_node(\n",
    "    \"keep_only_relevant_content\", keep_only_relevant_content\n",
    ")\n",
    "\n",
    "# Node: Rewrite the question for better retrieval if needed\n",
    "qualitative_retrieval_answer_workflow.add_node(\n",
    "    \"rewrite_question\", rewrite_question\n",
    ")\n",
    "\n",
    "# Node: Answer the question from the relevant context using LLM\n",
    "qualitative_retrieval_answer_workflow.add_node(\n",
    "    \"answer_question_from_context\", answer_question_from_context\n",
    ")\n",
    "\n",
    "# -------------------------\n",
    "# Build the Workflow Edges\n",
    "# -------------------------\n",
    "\n",
    "# Set the entry point of the workflow\n",
    "qualitative_retrieval_answer_workflow.set_entry_point(\"retrieve_context_per_question\")\n",
    "\n",
    "# Edge: After retrieving context, filter to keep only relevant content\n",
    "qualitative_retrieval_answer_workflow.add_edge(\n",
    "    \"retrieve_context_per_question\", \"keep_only_relevant_content\"\n",
    ")\n",
    "\n",
    "# Conditional Edge: After filtering, check if content is relevant\n",
    "# If relevant, answer the question; if not, rewrite the question\n",
    "qualitative_retrieval_answer_workflow.add_conditional_edges(\n",
    "    \"keep_only_relevant_content\",\n",
    "    is_relevant_content,\n",
    "    {\n",
    "        \"relevant\": \"answer_question_from_context\",\n",
    "        \"not relevant\": \"rewrite_question\"\n",
    "    },\n",
    ")\n",
    "\n",
    "# Edge: After rewriting the question, retrieve context again\n",
    "qualitative_retrieval_answer_workflow.add_edge(\n",
    "    \"rewrite_question\", \"retrieve_context_per_question\"\n",
    ")\n",
    "\n",
    "# Conditional Edge: After answering, grade the answer\n",
    "# If hallucination, try answering again; if not useful, rewrite question; if useful, end\n",
    "qualitative_retrieval_answer_workflow.add_conditional_edges(\n",
    "    \"answer_question_from_context\",\n",
    "    grade_generation_v_documents_and_question,\n",
    "    {\n",
    "        \"hallucination\": \"answer_question_from_context\",\n",
    "        \"not_useful\": \"rewrite_question\",\n",
    "        \"useful\": END\n",
    "    },\n",
    ")\n",
    "\n",
    "# Compile the workflow graph into an executable app\n",
    "qualitative_retrieval_answer_retrival_app = qualitative_retrieval_answer_workflow.compile()\n",
    "\n",
    "# Display the workflow graph as a Mermaid diagram\n",
    "display(\n",
    "    Image(\n",
    "        qualitative_retrieval_answer_retrival_app.get_graph().draw_mermaid_png(\n",
    "            draw_method=MermaidDrawMethod.API,\n",
    "        )\n",
    "    )\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "For more complex tasks, where the question cannot be answered solely by retrieving information based on semantic similarity, we need a more sophisticated pipeline. To achieve this, we may first break down the graph into several sub-graphs that will serve as functions for the sophisticated pipeline.\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Let's add a function that Verifies that the distilled content is grounded in the original context"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# --- Function: Check if Distilled Content is Grounded in the Original Context ---\n",
    "\n",
    "# Prompt template for the LLM to determine grounding\n",
    "is_distilled_content_grounded_on_content_prompt_template = \"\"\"\n",
    "You receive some distilled content: {distilled_content} and the original context: {original_context}.\n",
    "You need to determine if the distilled content is grounded on the original context.\n",
    "If the distilled content is grounded on the original context, set the grounded field to true.\n",
    "If the distilled content is not grounded on the original context, set the grounded field to false.\n",
    "{format_instructions}\n",
    "\"\"\"\n",
    "\n",
    "# Output schema for the LLM's response\n",
    "class IsDistilledContentGroundedOnContent(BaseModel):\n",
    "    grounded: bool = Field(\n",
    "        description=\"Whether the distilled content is grounded on the original context.\"\n",
    "    )\n",
    "    explanation: str = Field(\n",
    "        description=\"An explanation of why the distilled content is or is not grounded on the original context.\"\n",
    "    )\n",
    "\n",
    "# JSON parser for the output schema\n",
    "is_distilled_content_grounded_on_content_json_parser = JsonOutputParser(\n",
    "    pydantic_object=IsDistilledContentGroundedOnContent\n",
    ")\n",
    "\n",
    "# Create the prompt object for the LLM\n",
    "is_distilled_content_grounded_on_content_prompt = PromptTemplate(\n",
    "    template=is_distilled_content_grounded_on_content_prompt_template,\n",
    "    input_variables=[\"distilled_content\", \"original_context\"],\n",
    "    partial_variables={\n",
    "        \"format_instructions\": is_distilled_content_grounded_on_content_json_parser.get_format_instructions()\n",
    "    },\n",
    ")\n",
    "\n",
    "# Initialize the LLM for this task\n",
    "is_distilled_content_grounded_on_content_llm = ChatGroq(\n",
    "    temperature=0,\n",
    "    model_name=\"llama3-70b-8192\",\n",
    "    groq_api_key=groq_api_key,\n",
    "    max_tokens=4000\n",
    ")\n",
    "\n",
    "# Compose the chain: prompt -> LLM -> output parser\n",
    "is_distilled_content_grounded_on_content_chain = (\n",
    "    is_distilled_content_grounded_on_content_prompt\n",
    "    | is_distilled_content_grounded_on_content_llm\n",
    "    | is_distilled_content_grounded_on_content_json_parser\n",
    ")\n",
    "\n",
    "def is_distilled_content_grounded_on_content(state):\n",
    "    \"\"\"\n",
    "    Determines if the distilled content is grounded on the original context.\n",
    "\n",
    "    Args:\n",
    "        state (dict): A dictionary containing:\n",
    "            - \"relevant_context\": The distilled content.\n",
    "            - \"context\": The original context.\n",
    "\n",
    "    Returns:\n",
    "        str: \"grounded on the original context\" if grounded, otherwise \"not grounded on the original context\".\n",
    "    \"\"\"\n",
    "    pprint(\"--------------------\")\n",
    "    print(\"Determining if the distilled content is grounded on the original context...\")\n",
    "\n",
    "    distilled_content = state[\"relevant_context\"]\n",
    "    original_context = state[\"context\"]\n",
    "\n",
    "    input_data = {\n",
    "        \"distilled_content\": distilled_content,\n",
    "        \"original_context\": original_context\n",
    "    }\n",
    "\n",
    "    # Invoke the LLM chain to check grounding\n",
    "    output = is_distilled_content_grounded_on_content_chain.invoke(input_data)\n",
    "    grounded = output[\"grounded\"]\n",
    "\n",
    "    if grounded:\n",
    "        print(\"The distilled content is grounded on the original context.\")\n",
    "        return \"grounded on the original context\"\n",
    "    else:\n",
    "        print(\"The distilled content is not grounded on the original context.\")\n",
    "        return \"not grounded on the original context\""
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Create functions for each type of retrieval"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# -----------------------------------------------------------\n",
    "# Retrieval Functions for Different Context Types\n",
    "# -----------------------------------------------------------\n",
    "\n",
    "def retrieve_chunks_context_per_question(state):\n",
    "    \"\"\"\n",
    "    Retrieves relevant context for a given question from the book chunks.\n",
    "\n",
    "    Args:\n",
    "        state (dict): A dictionary containing the question to answer, with key \"question\".\n",
    "\n",
    "    Returns:\n",
    "        dict: A dictionary with keys:\n",
    "            - \"context\": Aggregated context string from relevant book chunks.\n",
    "            - \"question\": The original question.\n",
    "    \"\"\"\n",
    "    print(\"Retrieving relevant chunks...\")\n",
    "    question = state[\"question\"]\n",
    "    # Retrieve relevant book chunks using the retriever\n",
    "    docs = chunks_query_retriever.get_relevant_documents(question)\n",
    "    # Concatenate the content of the retrieved documents\n",
    "    context = \" \".join(doc.page_content for doc in docs)\n",
    "    context = escape_quotes(context)\n",
    "    return {\"context\": context, \"question\": question}\n",
    "\n",
    "def retrieve_summaries_context_per_question(state):\n",
    "    \"\"\"\n",
    "    Retrieves relevant context for a given question from chapter summaries.\n",
    "\n",
    "    Args:\n",
    "        state (dict): A dictionary containing the question to answer, with key \"question\".\n",
    "\n",
    "    Returns:\n",
    "        dict: A dictionary with keys:\n",
    "            - \"context\": Aggregated context string from relevant chapter summaries.\n",
    "            - \"question\": The original question.\n",
    "    \"\"\"\n",
    "    print(\"Retrieving relevant chapter summaries...\")\n",
    "    question = state[\"question\"]\n",
    "    # Retrieve relevant chapter summaries using the retriever\n",
    "    docs_summaries = chapter_summaries_query_retriever.get_relevant_documents(question)\n",
    "    # Concatenate the content of the retrieved summaries, including chapter citation\n",
    "    context_summaries = \" \".join(\n",
    "        f\"{doc.page_content} (Chapter {doc.metadata['chapter']})\" for doc in docs_summaries\n",
    "    )\n",
    "    context_summaries = escape_quotes(context_summaries)\n",
    "    return {\"context\": context_summaries, \"question\": question}\n",
    "\n",
    "def retrieve_book_quotes_context_per_question(state):\n",
    "    \"\"\"\n",
    "    Retrieves relevant context for a given question from book quotes.\n",
    "\n",
    "    Args:\n",
    "        state (dict): A dictionary containing the question to answer, with key \"question\".\n",
    "\n",
    "    Returns:\n",
    "        dict: A dictionary with keys:\n",
    "            - \"context\": Aggregated context string from relevant book quotes.\n",
    "            - \"question\": The original question.\n",
    "    \"\"\"\n",
    "    question = state[\"question\"]\n",
    "    print(\"Retrieving relevant book quotes...\")\n",
    "    # Retrieve relevant book quotes using the retriever\n",
    "    docs_book_quotes = book_quotes_query_retriever.get_relevant_documents(question)\n",
    "    # Concatenate the content of the retrieved quotes\n",
    "    book_quotes = \" \".join(doc.page_content for doc in docs_book_quotes)\n",
    "    book_quotes_context = escape_quotes(book_quotes)\n",
    "    return {\"context\": book_quotes_context, \"question\": question}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Create sub graph for each type of retrieval"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### The first sub-graph would be for retrieval and distillation of the relevant information with some modification"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "class QualitativeRetrievalGraphState(TypedDict):\n",
    "    \"\"\"\n",
    "    Represents the state of the qualitative retrieval graph.\n",
    "\n",
    "    Attributes:\n",
    "        question (str): The input question to be answered.\n",
    "        context (str): The context retrieved from the source (e.g., book chunks, summaries, or quotes).\n",
    "        relevant_context (str): The distilled or filtered context that is most relevant to the question.\n",
    "    \"\"\"\n",
    "    question: str\n",
    "    context: str\n",
    "    relevant_context: str"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/jpeg": "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",
      "text/plain": [
       "<IPython.core.display.Image object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# -----------------------------------------------------------\n",
    "# Qualitative Chunks Retrieval Workflow Graph Construction\n",
    "# -----------------------------------------------------------\n",
    "\n",
    "# 1. Create the workflow graph object with the appropriate state type\n",
    "qualitative_chunks_retrieval_workflow = StateGraph(QualitativeRetrievalGraphState)\n",
    "\n",
    "# 2. Define and add nodes to the graph\n",
    "# Node: Retrieve relevant context from book chunks for the question\n",
    "qualitative_chunks_retrieval_workflow.add_node(\n",
    "    \"retrieve_chunks_context_per_question\",\n",
    "    retrieve_chunks_context_per_question\n",
    ")\n",
    "# Node: Use LLM to keep only the relevant content from the retrieved context\n",
    "qualitative_chunks_retrieval_workflow.add_node(\n",
    "    \"keep_only_relevant_content\",\n",
    "    keep_only_relevant_content\n",
    ")\n",
    "\n",
    "# 3. Set the entry point of the workflow\n",
    "qualitative_chunks_retrieval_workflow.set_entry_point(\"retrieve_chunks_context_per_question\")\n",
    "\n",
    "# 4. Add edges to define the workflow\n",
    "# After retrieving context, filter to keep only relevant content\n",
    "qualitative_chunks_retrieval_workflow.add_edge(\n",
    "    \"retrieve_chunks_context_per_question\",\n",
    "    \"keep_only_relevant_content\"\n",
    ")\n",
    "\n",
    "# Conditional edge: After filtering, check if distilled content is grounded in the original context\n",
    "# If grounded, end; if not, repeat filtering\n",
    "qualitative_chunks_retrieval_workflow.add_conditional_edges(\n",
    "    \"keep_only_relevant_content\",\n",
    "    is_distilled_content_grounded_on_content,\n",
    "    {\n",
    "        \"grounded on the original context\": END,\n",
    "        \"not grounded on the original context\": \"keep_only_relevant_content\"\n",
    "    },\n",
    ")\n",
    "\n",
    "# 5. Compile the workflow graph into an executable app\n",
    "qualitative_chunks_retrieval_workflow_app = qualitative_chunks_retrieval_workflow.compile()\n",
    "\n",
    "# 6. Display the workflow graph as a Mermaid diagram\n",
    "display(\n",
    "    Image(\n",
    "        qualitative_chunks_retrieval_workflow_app.get_graph().draw_mermaid_png(\n",
    "            draw_method=MermaidDrawMethod.API,\n",
    "        )\n",
    "    )\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/jpeg": "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",
      "text/plain": [
       "<IPython.core.display.Image object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# -----------------------------------------------------------\n",
    "# Qualitative Summaries Retrieval Workflow Graph Construction\n",
    "# -----------------------------------------------------------\n",
    "\n",
    "# 1. Create the workflow graph object with the appropriate state type\n",
    "qualitative_summaries_retrieval_workflow = StateGraph(QualitativeRetrievalGraphState)\n",
    "\n",
    "# 2. Define and add nodes to the graph\n",
    "# Node: Retrieve relevant context from chapter summaries for the question\n",
    "qualitative_summaries_retrieval_workflow.add_node(\n",
    "    \"retrieve_summaries_context_per_question\",\n",
    "    retrieve_summaries_context_per_question\n",
    ")\n",
    "# Node: Use LLM to keep only the relevant content from the retrieved context\n",
    "qualitative_summaries_retrieval_workflow.add_node(\n",
    "    \"keep_only_relevant_content\",\n",
    "    keep_only_relevant_content\n",
    ")\n",
    "\n",
    "# 3. Set the entry point of the workflow\n",
    "qualitative_summaries_retrieval_workflow.set_entry_point(\"retrieve_summaries_context_per_question\")\n",
    "\n",
    "# 4. Add edges to define the workflow\n",
    "# After retrieving context, filter to keep only relevant content\n",
    "qualitative_summaries_retrieval_workflow.add_edge(\n",
    "    \"retrieve_summaries_context_per_question\",\n",
    "    \"keep_only_relevant_content\"\n",
    ")\n",
    "\n",
    "# Conditional edge: After filtering, check if distilled content is grounded in the original context\n",
    "# If grounded, end; if not, repeat filtering\n",
    "qualitative_summaries_retrieval_workflow.add_conditional_edges(\n",
    "    \"keep_only_relevant_content\",\n",
    "    is_distilled_content_grounded_on_content,\n",
    "    {\n",
    "        \"grounded on the original context\": END,\n",
    "        \"not grounded on the original context\": \"keep_only_relevant_content\"\n",
    "    },\n",
    ")\n",
    "\n",
    "# 5. Compile the workflow graph into an executable app\n",
    "qualitative_summaries_retrieval_workflow_app = qualitative_summaries_retrieval_workflow.compile()\n",
    "\n",
    "# 6. Display the workflow graph as a Mermaid diagram\n",
    "display(\n",
    "    Image(\n",
    "        qualitative_summaries_retrieval_workflow_app.get_graph().draw_mermaid_png(\n",
    "            draw_method=MermaidDrawMethod.API,\n",
    "        )\n",
    "    )\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/jpeg": "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",
      "text/plain": [
       "<IPython.core.display.Image object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# -----------------------------------------------------------\n",
    "# Qualitative Book Quotes Retrieval Workflow Graph Construction\n",
    "# -----------------------------------------------------------\n",
    "\n",
    "# 1. Create the workflow graph object with the appropriate state type\n",
    "qualitative_book_quotes_retrieval_workflow = StateGraph(QualitativeRetrievalGraphState)\n",
    "\n",
    "# 2. Define and add nodes to the graph\n",
    "# Node: Retrieve relevant context from book quotes for the question\n",
    "qualitative_book_quotes_retrieval_workflow.add_node(\n",
    "    \"retrieve_book_quotes_context_per_question\",\n",
    "    retrieve_book_quotes_context_per_question\n",
    ")\n",
    "# Node: Use LLM to keep only the relevant content from the retrieved context\n",
    "qualitative_book_quotes_retrieval_workflow.add_node(\n",
    "    \"keep_only_relevant_content\",\n",
    "    keep_only_relevant_content\n",
    ")\n",
    "\n",
    "# 3. Set the entry point of the workflow\n",
    "qualitative_book_quotes_retrieval_workflow.set_entry_point(\"retrieve_book_quotes_context_per_question\")\n",
    "\n",
    "# 4. Add edges to define the workflow\n",
    "# After retrieving context, filter to keep only relevant content\n",
    "qualitative_book_quotes_retrieval_workflow.add_edge(\n",
    "    \"retrieve_book_quotes_context_per_question\",\n",
    "    \"keep_only_relevant_content\"\n",
    ")\n",
    "\n",
    "# Conditional edge: After filtering, check if distilled content is grounded in the original context\n",
    "# If grounded, end; if not, repeat filtering\n",
    "qualitative_book_quotes_retrieval_workflow.add_conditional_edges(\n",
    "    \"keep_only_relevant_content\",\n",
    "    is_distilled_content_grounded_on_content,\n",
    "    {\n",
    "        \"grounded on the original context\": END,\n",
    "        \"not grounded on the original context\": \"keep_only_relevant_content\"\n",
    "    },\n",
    ")\n",
    "\n",
    "# 5. Compile the workflow graph into an executable app\n",
    "qualitative_book_quotes_retrieval_workflow_app = qualitative_book_quotes_retrieval_workflow.compile()\n",
    "\n",
    "# 6. Display the workflow graph as a Mermaid diagram\n",
    "display(\n",
    "    Image(\n",
    "        qualitative_book_quotes_retrieval_workflow_app.get_graph().draw_mermaid_png(\n",
    "            draw_method=MermaidDrawMethod.API,\n",
    "        )\n",
    "    )\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Test the retreive-and-keep-relevant-content graphs"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# -----------------------------------------------------------\n",
    "# Initialize the state for the retrieval/answering pipeline\n",
    "# -----------------------------------------------------------\n",
    "# This dictionary defines the initial state for the workflow,\n",
    "# specifying the question to be answered.\n",
    "# You can modify the \"question\" value to test different queries.\n",
    "init_state = {\n",
    "    \"question\": \"worse than getting killed\"  # The question to answer\n",
    "}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# -----------------------------------------------------------\n",
    "# Test the book chunks retrieval workflow\n",
    "# -----------------------------------------------------------\n",
    "\n",
    "# Stream the outputs from the qualitative_chunks_retrieval_workflow_app\n",
    "# for the given initial state (init_state contains the question to answer).\n",
    "for output in qualitative_chunks_retrieval_workflow_app.stream(init_state):\n",
    "    # Iterate through the output items (node name, value)\n",
    "    for _, value in output.items():\n",
    "        pass  # The value variable will hold the latest state after each node execution\n",
    "    pprint(\"--------------------\")  # Print a separator for clarity between steps\n",
    "\n",
    "# After the workflow completes, print the final relevant context extracted\n",
    "print(f'relevant context: {value[\"relevant_context\"]}')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# -----------------------------------------------------------\n",
    "# Test the chapter summaries retrieval workflow\n",
    "# -----------------------------------------------------------\n",
    "\n",
    "# Stream the outputs from the qualitative_summaries_retrieval_workflow_app\n",
    "# for the given initial state (init_state contains the question to answer).\n",
    "for output in qualitative_summaries_retrieval_workflow_app.stream(init_state):\n",
    "    # Iterate through the output items (node name, value)\n",
    "    for _, value in output.items():\n",
    "        pass  # The value variable will hold the latest state after each node execution\n",
    "    pprint(\"--------------------\")  # Print a separator for clarity between steps\n",
    "\n",
    "# After the workflow completes, print the final relevant context extracted\n",
    "print(f'relevant context: {value[\"relevant_context\"]}')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# -----------------------------------------------------------\n",
    "# Test the book quotes retrieval workflow\n",
    "# -----------------------------------------------------------\n",
    "\n",
    "# Stream the outputs from the qualitative_book_quotes_retrieval_workflow_app\n",
    "# for the given initial state (init_state contains the question to answer).\n",
    "for output in qualitative_book_quotes_retrieval_workflow_app.stream(init_state):\n",
    "    # Iterate through the output items (node name, value)\n",
    "    for _, value in output.items():\n",
    "        pass  # The value variable will hold the latest state after each node execution\n",
    "    pprint(\"--------------------\")  # Print a separator for clarity between steps\n",
    "\n",
    "# After the workflow completes, print the final relevant context extracted\n",
    "print(f'relevant context: {value[\"relevant_context\"]}')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Add a shorter version of the answer verification, checking only if grounded on context"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "def is_answer_grounded_on_context(state):\n",
    "    \"\"\"\n",
    "    Determines if the answer to the question is grounded in the provided context (i.e., not a hallucination).\n",
    "\n",
    "    Args:\n",
    "        state (dict): A dictionary containing:\n",
    "            - \"context\": The context used to answer the question.\n",
    "            - \"answer\": The generated answer to the question.\n",
    "\n",
    "    Returns:\n",
    "        str: \"hallucination\" if the answer is not grounded in the context, \n",
    "             \"grounded on context\" if the answer is supported by the context.\n",
    "    \"\"\"\n",
    "    print(\"Checking if the answer is grounded in the facts...\")\n",
    "\n",
    "    # Extract context and answer from the state\n",
    "    context = state[\"context\"]\n",
    "    answer = state[\"answer\"]\n",
    "\n",
    "    # Use the LLM chain to check if the answer is grounded in the context\n",
    "    result = is_grounded_on_facts_chain.invoke({\"context\": context, \"answer\": answer})\n",
    "    grounded_on_facts = result.grounded_on_facts\n",
    "\n",
    "    # Return the result based on grounding\n",
    "    if not grounded_on_facts:\n",
    "        print(\"The answer is hallucination.\")\n",
    "        return \"hallucination\"\n",
    "    else:\n",
    "        print(\"The answer is grounded in the facts.\")\n",
    "        return \"grounded on context\""
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### The last sub-graph will be a component that answers a question given context, without hallucinations"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/jpeg": "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",
      "text/plain": [
       "<IPython.core.display.Image object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# -----------------------------------------------\n",
    "# Qualitative Answer Workflow Graph Construction\n",
    "# -----------------------------------------------\n",
    "\n",
    "# Define the state for the answer workflow graph\n",
    "class QualitativeAnswerGraphState(TypedDict):\n",
    "    \"\"\"\n",
    "    Represents the state of the qualitative answer graph.\n",
    "\n",
    "    Attributes:\n",
    "        question (str): The input question to be answered.\n",
    "        context (str): The context used to answer the question.\n",
    "        answer (str): The generated answer to the question.\n",
    "    \"\"\"\n",
    "    question: str\n",
    "    context: str\n",
    "    answer: str\n",
    "\n",
    "# Create the workflow graph object\n",
    "qualitative_answer_workflow = StateGraph(QualitativeAnswerGraphState)\n",
    "\n",
    "# -------------------------\n",
    "# Define and Add Graph Nodes\n",
    "# -------------------------\n",
    "\n",
    "# Node: Answer the question from the provided context using LLM\n",
    "qualitative_answer_workflow.add_node(\n",
    "    \"answer_question_from_context\",\n",
    "    answer_question_from_context\n",
    ")\n",
    "\n",
    "# -------------------------\n",
    "# Build the Workflow Edges\n",
    "# -------------------------\n",
    "\n",
    "# Set the entry point of the workflow\n",
    "qualitative_answer_workflow.set_entry_point(\"answer_question_from_context\")\n",
    "\n",
    "# Conditional Edge: After answering, check if the answer is grounded in the context\n",
    "# If hallucination, try answering again; if grounded, end\n",
    "qualitative_answer_workflow.add_conditional_edges(\n",
    "    \"answer_question_from_context\",\n",
    "    is_answer_grounded_on_context,\n",
    "    {\n",
    "        \"hallucination\": \"answer_question_from_context\",\n",
    "        \"grounded on context\": END\n",
    "    }\n",
    ")\n",
    "\n",
    "# Compile the workflow graph into an executable app\n",
    "qualitative_answer_workflow_app = qualitative_answer_workflow.compile()\n",
    "\n",
    "# Display the workflow graph as a Mermaid diagram\n",
    "display(\n",
    "    Image(\n",
    "        qualitative_answer_workflow_app.get_graph().draw_mermaid_png(\n",
    "            draw_method=MermaidDrawMethod.API,\n",
    "        )\n",
    "    )\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Test the answer-from-question-graph"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Answering the question from the retrieved context...\n",
      "answer before checking hallucination: The context states that Harry Potter is a cat. Therefore, Harry is a cat.\n",
      "Checking if the answer is grounded in the facts...\n",
      "The answer is grounded in the facts.\n",
      "'--------------------'\n",
      "answer: The context states that Harry Potter is a cat. Therefore, Harry is a cat.\n"
     ]
    }
   ],
   "source": [
    "# -----------------------------------------------\n",
    "# Test the qualitative answer workflow graph\n",
    "# -----------------------------------------------\n",
    "\n",
    "# Define the question and context for the test\n",
    "question = \"who is harry?\"  # The question to answer\n",
    "context = \"Harry Potter is a cat.\"  # The context to answer the question from\n",
    "\n",
    "# Initialize the state for the workflow\n",
    "init_state = {\n",
    "    \"question\": question,\n",
    "    \"context\": context\n",
    "}\n",
    "\n",
    "# Stream the outputs from the qualitative_answer_workflow_app\n",
    "# This will execute each node in the workflow step by step\n",
    "for output in qualitative_answer_workflow_app.stream(init_state):\n",
    "    # Iterate through the output items (node name, value)\n",
    "    for _, value in output.items():\n",
    "        pass  # The value variable holds the latest state after each node execution\n",
    "    pprint(\"--------------------\")  # Print a separator for clarity between steps\n",
    "\n",
    "# After the workflow completes, print the final answer generated by the workflow\n",
    "print(f'answer: {value[\"answer\"]}')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Now let's define the sophisticated pipeline components"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### The state of each step of the graph should be in this structure:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import TypedDict, List, Dict\n",
    "\n",
    "class PlanExecute(TypedDict):\n",
    "    \"\"\"\n",
    "    Represents the state at each step of the plan execution pipeline.\n",
    "\n",
    "    Attributes:\n",
    "        curr_state (str): The current state or status of the execution.\n",
    "        question (str): The original user question.\n",
    "        anonymized_question (str): The anonymized version of the question (entities replaced with variables).\n",
    "        query_to_retrieve_or_answer (str): The query to be used for retrieval or answering.\n",
    "        plan (List[str]): The current plan as a list of steps to execute.\n",
    "        past_steps (List[str]): List of steps that have already been executed.\n",
    "        mapping (dict): Mapping of anonymized variables to original named entities.\n",
    "        curr_context (str): The current context used for answering or retrieval.\n",
    "        aggregated_context (str): The accumulated context from previous steps.\n",
    "        tool (str): The tool or method used for the current step (e.g., retrieval, answer).\n",
    "        response (str): The response or output generated at this step.\n",
    "    \"\"\"\n",
    "    curr_state: str\n",
    "    question: str\n",
    "    anonymized_question: str\n",
    "    query_to_retrieve_or_answer: str\n",
    "    plan: List[str]\n",
    "    past_steps: List[str]\n",
    "    mapping: Dict[str, str]\n",
    "    curr_context: str\n",
    "    aggregated_context: str\n",
    "    tool: str\n",
    "    response: str"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Define the Plan node - constructs a plan composed of steps, of how to tackle a question"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "from langchain_core.prompts import PromptTemplate\n",
    "from langchain_core.pydantic_v1 import BaseModel, Field\n",
    "\n",
    "# -----------------------------------------------\n",
    "# Planning Component for Multi-Step Question Answering\n",
    "# -----------------------------------------------\n",
    "\n",
    "\n",
    "# Define the output schema for the plan\n",
    "class Plan(BaseModel):\n",
    "    \"\"\"\n",
    "    Represents a step-by-step plan to answer a given question.\n",
    "    Attributes:\n",
    "        steps (List[str]): Ordered list of steps to follow.\n",
    "    \"\"\"\n",
    "    steps: List[str] = Field(\n",
    "        description=\"different steps to follow, should be in sorted order\"\n",
    "    )\n",
    "\n",
    "# Prompt template for generating a plan from a question\n",
    "planner_prompt = \"\"\"\n",
    "For the given query {question}, come up with a simple step by step plan of how to figure out the answer. \n",
    "\n",
    "This plan should involve individual tasks, that if executed correctly will yield the correct answer. Do not add any superfluous steps. \n",
    "The result of the final step should be the final answer. Make sure that each step has all the information needed - do not skip steps.\n",
    "\"\"\"\n",
    "\n",
    "planner_prompt = PromptTemplate(\n",
    "    template=planner_prompt,\n",
    "    input_variables=[\"question\"],\n",
    ")\n",
    "\n",
    "# Initialize the LLM for planning (using GPT-4o)\n",
    "planner_llm = ChatOpenAI(\n",
    "    temperature=0,\n",
    "    model_name=\"gpt-4o\",\n",
    "    max_tokens=2000\n",
    ")\n",
    "\n",
    "# Compose the planning chain: prompt -> LLM -> structured output\n",
    "planner = planner_prompt | planner_llm.with_structured_output(Plan)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### A function to break down each task to either retrieve or answer"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# -----------------------------------------------------------\n",
    "# Chain to Refine a Plan into Executable Steps for Retrieval/Answering\n",
    "# -----------------------------------------------------------\n",
    "\n",
    "# Prompt template for refining a plan so that each step is executable by a retrieval or answer operation\n",
    "break_down_plan_prompt_template = \"\"\"\n",
    "You receive a plan {plan} which contains a series of steps to follow in order to answer a query. \n",
    "You need to go through the plan and refine it according to these rules:\n",
    "1. Every step must be executable by one of the following:\n",
    "    i. Retrieving relevant information from a vector store of book chunks\n",
    "    ii. Retrieving relevant information from a vector store of chapter summaries\n",
    "    iii. Retrieving relevant information from a vector store of book quotes\n",
    "    iv. Answering a question from a given context.\n",
    "2. Every step should contain all the information needed to execute it.\n",
    "\n",
    "Output the refined plan.\n",
    "\"\"\"\n",
    "\n",
    "# Create a PromptTemplate for the LLM\n",
    "break_down_plan_prompt = PromptTemplate(\n",
    "    template=break_down_plan_prompt_template,\n",
    "    input_variables=[\"plan\"],\n",
    ")\n",
    "\n",
    "# Initialize the LLM for plan breakdown (using GPT-4o)\n",
    "break_down_plan_llm = ChatOpenAI(\n",
    "    temperature=0,\n",
    "    model_name=\"gpt-4o\",\n",
    "    max_tokens=2000\n",
    ")\n",
    "\n",
    "# Compose the chain: prompt -> LLM -> structured output (Plan)\n",
    "break_down_plan_chain = break_down_plan_prompt | break_down_plan_llm.with_structured_output(Plan)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Example of how to use the planner\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "steps=['Identify the main character and the villain in the story.', 'Locate the climax or the final confrontation between the main character and the villain.', 'Analyze the actions taken by the main character during this confrontation.', 'Determine the specific action or strategy that led to the defeat of the villain.', 'Summarize the findings to answer how the main character beat the villain.']\n",
      "steps=['Identify the main character and the villain in the story by retrieving relevant information from a vector store of book chunks, chapter summaries, or book quotes.', 'Locate the climax or the final confrontation between the main character and the villain by retrieving relevant information from a vector store of book chunks, chapter summaries, or book quotes.', 'Analyze the actions taken by the main character during this confrontation by retrieving relevant information from a vector store of book chunks, chapter summaries, or book quotes.', 'Determine the specific action or strategy that led to the defeat of the villain by retrieving relevant information from a vector store of book chunks, chapter summaries, or book quotes.', 'Summarize the findings to answer how the main character beat the villain by answering a question from a given context.']\n"
     ]
    }
   ],
   "source": [
    "# -----------------------------------------------------------\n",
    "# Example: How to Use the Planner and Refine the Plan\n",
    "# -----------------------------------------------------------\n",
    "\n",
    "# 1. Define the question to answer\n",
    "question = {\"question\": \"how did the main character beat the villain?\"}\n",
    "\n",
    "# 2. Generate a step-by-step plan to answer the question using the planner chain\n",
    "my_plan = planner.invoke(question)\n",
    "print(\"Initial Plan:\")\n",
    "print(my_plan)\n",
    "\n",
    "# 3. Refine the plan so that each step is executable by a retrieval or answer operation\n",
    "refined_plan = break_down_plan_chain.invoke(my_plan.steps)\n",
    "print(\"\\nRefined Plan:\")\n",
    "print(refined_plan)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Given the original question, the current plan, the past steps, and the so far aggregated information, update the plan"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# -----------------------------------------------------------\n",
    "# Replanner: Update Plan Based on Progress and Aggregated Context\n",
    "# -----------------------------------------------------------\n",
    "\n",
    "# Define a Pydantic model for the possible results of the replanning action\n",
    "class ActPossibleResults(BaseModel):\n",
    "    \"\"\"\n",
    "    Represents the possible results of the replanning action.\n",
    "\n",
    "    Attributes:\n",
    "        plan (Plan): The updated plan to follow in the future.\n",
    "        explanation (str): Explanation of the action taken or the reasoning behind the plan update.\n",
    "    \"\"\"\n",
    "    plan: Plan = Field(description=\"Plan to follow in future.\")\n",
    "    explanation: str = Field(description=\"Explanation of the action.\")\n",
    "\n",
    "# Create a JSON output parser for the ActPossibleResults schema\n",
    "act_possible_results_parser = JsonOutputParser(pydantic_object=ActPossibleResults)\n",
    "\n",
    "# Prompt template for replanning, instructing the LLM to update the plan based on the current state\n",
    "replanner_prompt_template = \"\"\"\n",
    "For the given objective, come up with a simple step by step plan of how to figure out the answer. \n",
    "This plan should involve individual tasks, that if executed correctly will yield the correct answer. Do not add any superfluous steps. \n",
    "The result of the final step should be the final answer. Make sure that each step has all the information needed - do not skip steps.\n",
    "\n",
    "Assume that the answer was not found yet and you need to update the plan accordingly, so the plan should never be empty.\n",
    "\n",
    "Your objective was this:\n",
    "{question}\n",
    "\n",
    "Your original plan was this:\n",
    "{plan}\n",
    "\n",
    "You have currently done the follow steps:\n",
    "{past_steps}\n",
    "\n",
    "You already have the following context:\n",
    "{aggregated_context}\n",
    "\n",
    "Update your plan accordingly. If further steps are needed, fill out the plan with only those steps.\n",
    "Do not return previously done steps as part of the plan.\n",
    "\n",
    "The format is JSON so escape quotes and new lines.\n",
    "\n",
    "{format_instructions}\n",
    "\"\"\"\n",
    "\n",
    "# Create a PromptTemplate object for the replanner\n",
    "replanner_prompt = PromptTemplate(\n",
    "    template=replanner_prompt_template,\n",
    "    input_variables=[\"question\", \"plan\", \"past_steps\", \"aggregated_context\"],\n",
    "    partial_variables={\"format_instructions\": act_possible_results_parser.get_format_instructions()},\n",
    ")\n",
    "\n",
    "# Initialize the LLM for replanning (using GPT-4o)\n",
    "replanner_llm = ChatOpenAI(\n",
    "    temperature=0,\n",
    "    model_name=\"gpt-4o\",\n",
    "    max_tokens=2000\n",
    ")\n",
    "\n",
    "# Compose the replanner chain: prompt -> LLM -> output parser\n",
    "replanner = replanner_prompt | replanner_llm | act_possible_results_parser"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Define the task handler - decides whether to use the first sub-graph or the second sub-graph to handle each task from the plan"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# -----------------------------------------------------------\n",
    "# Task Handler: Decide Which Tool to Use for Each Task\n",
    "# -----------------------------------------------------------\n",
    "\n",
    "# Prompt template for the task handler LLM\n",
    "tasks_handler_prompt_template = \"\"\"\n",
    "You are a task handler that receives a task {curr_task} and have to decide with tool to use to execute the task.\n",
    "You have the following tools at your disposal:\n",
    "Tool A: a tool that retrieves relevant information from a vector store of book chunks based on a given query.\n",
    "- use Tool A when you think the current task should search for information in the book chunks.\n",
    "Tool B: a tool that retrieves relevant information from a vector store of chapter summaries based on a given query.\n",
    "- use Tool B when you think the current task should search for information in the chapter summaries.\n",
    "Tool C: a tool that retrieves relevant information from a vector store of quotes from the book based on a given query.\n",
    "- use Tool C when you think the current task should search for information in the book quotes.\n",
    "Tool D: a tool that answers a question from a given context.\n",
    "- use Tool D ONLY when you the current task can be answered by the aggregated context {aggregated_context}\n",
    "\n",
    "You also receive the last tool used {last_tool}\n",
    "if {last_tool} was retrieve_chunks, use other tools than Tool A.\n",
    "\n",
    "You also have the past steps {past_steps} that you can use to make decisions and understand the context of the task.\n",
    "You also have the initial user's question {question} that you can use to make decisions and understand the context of the task.\n",
    "if you decide to use Tools A,B or C, output the query to be used for the tool and also output the relevant tool.\n",
    "if you decide to use Tool D, output the question to be used for the tool, the context, and also that the tool to be used is Tool D.\n",
    "\"\"\"\n",
    "\n",
    "# Output schema for the task handler\n",
    "class TaskHandlerOutput(BaseModel):\n",
    "    \"\"\"\n",
    "    Output schema for the task handler.\n",
    "    - query: The query to be either retrieved from the vector store, or the question that should be answered from context.\n",
    "    - curr_context: The context to be based on in order to answer the query.\n",
    "    - tool: The tool to be used; should be one of 'retrieve_chunks', 'retrieve_summaries', 'retrieve_quotes', or 'answer_from_context'.\n",
    "    \"\"\"\n",
    "    query: str = Field(description=\"The query to be either retrieved from the vector store, or the question that should be answered from context.\")\n",
    "    curr_context: str = Field(description=\"The context to be based on in order to answer the query.\")\n",
    "    tool: str = Field(description=\"The tool to be used should be either retrieve_chunks, retrieve_summaries, retrieve_quotes, or answer_from_context.\")\n",
    "\n",
    "# Create the prompt object for the task handler\n",
    "task_handler_prompt = PromptTemplate(\n",
    "    template=tasks_handler_prompt_template,\n",
    "    input_variables=[\"curr_task\", \"aggregated_context\", \"last_tool\", \"past_steps\", \"question\"],\n",
    ")\n",
    "\n",
    "# Initialize the LLM for the task handler (using GPT-4o)\n",
    "task_handler_llm = ChatOpenAI(\n",
    "    temperature=0,\n",
    "    model_name=\"gpt-4o\",\n",
    "    max_tokens=2000\n",
    ")\n",
    "\n",
    "# Compose the task handler chain: prompt -> LLM -> structured output\n",
    "task_handler_chain = task_handler_prompt | task_handler_llm.with_structured_output(TaskHandlerOutput)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### In order to generate a general plan, without any biases based on prior knowledge of any LLM, we anonymize the input question, first, and map the name entities into variables"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# -----------------------------------------------------------\n",
    "# Anonymize Question Chain: Replace Named Entities with Variables\n",
    "# -----------------------------------------------------------\n",
    "\n",
    "# Define a Pydantic model for the anonymized question output\n",
    "class AnonymizeQuestion(BaseModel):\n",
    "  \"\"\"\n",
    "  Output schema for the anonymized question.\n",
    "  Attributes:\n",
    "    anonymized_question (str): The question with named entities replaced by variables.\n",
    "    mapping (dict): Mapping of variables to original named entities.\n",
    "    explanation (str): Explanation of the anonymization process.\n",
    "  \"\"\"\n",
    "  anonymized_question: str = Field(description=\"Anonymized question.\")\n",
    "  mapping: dict = Field(description=\"Mapping of original name entities to variables.\")\n",
    "  explanation: str = Field(description=\"Explanation of the action.\")\n",
    "\n",
    "# Create a JSON output parser for the AnonymizeQuestion schema\n",
    "anonymize_question_parser = JsonOutputParser(pydantic_object=AnonymizeQuestion)\n",
    "\n",
    "# Prompt template for the LLM to anonymize questions\n",
    "anonymize_question_prompt_template = \"\"\"\n",
    "You are a question anonymizer. The input you receive is a string containing several words that\n",
    "construct a question {question}. Your goal is to change all name entities in the input to variables, and remember the mapping of the original name entities to the variables.\n",
    "Example 1:\n",
    "  if the input is \"who is harry potter?\" the output should be \"who is X?\" and the mapping should be {{\"X\": \"harry potter\"}}\n",
    "Example 2:\n",
    "  if the input is \"how did the bad guy played with the alex and rony?\"\n",
    "  the output should be \"how did the X played with the Y and Z?\" and the mapping should be {{\"X\": \"bad guy\", \"Y\": \"alex\", \"Z\": \"rony\"}}\n",
    "You must replace all name entities in the input with variables, and remember the mapping of the original name entities to the variables.\n",
    "Output the anonymized question and the mapping in a JSON format.\n",
    "{format_instructions}\n",
    "\"\"\"\n",
    "\n",
    "# Create the PromptTemplate object for the anonymization task\n",
    "anonymize_question_prompt = PromptTemplate(\n",
    "  template=anonymize_question_prompt_template,\n",
    "  input_variables=[\"question\"],\n",
    "  partial_variables={\"format_instructions\": anonymize_question_parser.get_format_instructions()},\n",
    ")\n",
    "\n",
    "# Initialize the LLM for anonymization (using GPT-4o)\n",
    "anonymize_question_llm = ChatOpenAI(\n",
    "  temperature=0,\n",
    "  model_name=\"gpt-4o\",\n",
    "  max_tokens=2000\n",
    ")\n",
    "\n",
    "# Compose the anonymization chain: prompt -> LLM -> output parser\n",
    "anonymize_question_chain = (\n",
    "  anonymize_question_prompt\n",
    "  | anonymize_question_llm\n",
    "  | anonymize_question_parser\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### After the plan is constructed based on the anonymized question, we de-anonymize the plan, using the mapped variables"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from langchain_core.pydantic_v1 import BaseModel, Field\n",
    "from typing import List\n",
    "\n",
    "# -----------------------------------------------------------\n",
    "# De-Anonymize Plan Chain: Replace Variables in Plan with Mapped Words\n",
    "# -----------------------------------------------------------\n",
    "\n",
    "\n",
    "class DeAnonymizePlan(BaseModel):\n",
    "    \"\"\"\n",
    "    Output schema for the de-anonymized plan.\n",
    "    Attributes:\n",
    "        plan (List): Plan to follow in future, with all variables replaced by the mapped words.\n",
    "    \"\"\"\n",
    "    plan: List = Field(\n",
    "        description=\"Plan to follow in future. with all the variables replaced with the mapped words.\"\n",
    "    )\n",
    "\n",
    "# Prompt template for de-anonymizing a plan\n",
    "de_anonymize_plan_prompt_template = (\n",
    "    \"You receive a list of tasks: {plan}, where some of the words are replaced with mapped variables. \"\n",
    "    \"You also receive the mapping for those variables to words {mapping}. \"\n",
    "    \"Replace all the variables in the list of tasks with the mapped words. \"\n",
    "    \"If no variables are present, return the original list of tasks. \"\n",
    "    \"In any case, just output the updated list of tasks in a JSON format as described here, \"\n",
    "    \"without any additional text apart from the JSON.\"\n",
    ")\n",
    "\n",
    "# Create the PromptTemplate object for the de-anonymization task\n",
    "de_anonymize_plan_prompt = PromptTemplate(\n",
    "    template=de_anonymize_plan_prompt_template,\n",
    "    input_variables=[\"plan\", \"mapping\"],\n",
    ")\n",
    "\n",
    "# Initialize the LLM for de-anonymization (using GPT-4o)\n",
    "de_anonymize_plan_llm = ChatOpenAI(\n",
    "    temperature=0,\n",
    "    model_name=\"gpt-4o\",\n",
    "    max_tokens=2000\n",
    ")\n",
    "\n",
    "# Compose the de-anonymization chain: prompt -> LLM -> structured output\n",
    "de_anonymize_plan_chain = (\n",
    "    de_anonymize_plan_prompt\n",
    "    | de_anonymize_plan_llm.with_structured_output(DeAnonymizePlan)\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Example of how to build a plan\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "question: how did the harry beat quirrell? \n",
      "\n",
      "anonimized_querry: how did the X beat Y? \n",
      "\n",
      "mapping: {'X': 'harry', 'Y': 'quirrell'} \n",
      "\n",
      "plan: ['Identify the context or domain of the query (e.g., sports, competition, game, etc.).', 'Gather information about\n",
      "the event or competition where X and Y participated.', 'Find the specific instance or match where X competed against\n",
      "Y.', 'Look up the results of that specific instance or match.', 'Analyze the details of the match to understand how X\n",
      "managed to beat Y.', 'Summarize the key points that explain how X beat Y.']\n",
      "\n",
      "deanonimized_plan: ['Identify the context or domain of the query (e.g., sports, competition, game, etc.).', 'Gather\n",
      "information about the event or competition where harry and quirrell participated.', 'Find the specific instance or match\n",
      "where harry competed against quirrell.', 'Look up the results of that specific instance or match.', 'Analyze the details\n",
      "of the match to understand how harry managed to beat quirrell.', 'Summarize the key points that explain how harry beat\n",
      "quirrell.']\n"
     ]
    }
   ],
   "source": [
    "# -----------------------------------------------------------\n",
    "# Example: Anonymize, Plan, and De-anonymize a Question\n",
    "# -----------------------------------------------------------\n",
    "\n",
    "# 1. Define the question to answer\n",
    "state1 = {\n",
    "    'question': \"how did the harry beat quirrell? \\n\"\n",
    "}\n",
    "print(f'question: {state1[\"question\"]}')\n",
    "\n",
    "# 2. Anonymize the question (replace named entities with variables)\n",
    "anonymized_question_output = anonymize_question_chain.invoke(state1)\n",
    "anonymized_question = anonymized_question_output[\"anonymized_question\"]  # The anonymized question\n",
    "mapping = anonymized_question_output[\"mapping\"]  # Mapping of variables to original entities\n",
    "\n",
    "print(f'anonymized_query: {anonymized_question} \\n')\n",
    "print(f'mapping: {mapping} \\n')\n",
    "\n",
    "# 3. Generate a step-by-step plan for the anonymized question\n",
    "plan = planner.invoke({\"question\": anonymized_question})\n",
    "print(text_wrap(f'plan: {plan.steps}'))\n",
    "print(\"\")\n",
    "\n",
    "# 4. De-anonymize the plan (replace variables back with original entities)\n",
    "deanonymized_plan = de_anonymize_plan_chain.invoke({\n",
    "    \"plan\": plan.steps,\n",
    "    \"mapping\": mapping\n",
    "})\n",
    "print(text_wrap(f'deanonymized_plan: {deanonymized_plan.plan}'))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### A function that checks if the final answer can be deduced already, based on the aggregated information"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# -----------------------------------------------------------\n",
    "# LLM Chain: Check if a Question Can Be Fully Answered from Context\n",
    "# -----------------------------------------------------------\n",
    "\n",
    "# Define the output schema for the LLM's response\n",
    "class CanBeAnsweredAlready(BaseModel):\n",
    "    \"\"\"\n",
    "    Output schema for checking if the question can be fully answered from the given context.\n",
    "    Attributes:\n",
    "        can_be_answered (bool): Whether the question can be fully answered or not based on the given context.\n",
    "    \"\"\"\n",
    "    can_be_answered: bool = Field(\n",
    "        description=\"Whether the question can be fully answered or not based on the given context.\"\n",
    "    )\n",
    "\n",
    "# Prompt template for the LLM to determine answerability\n",
    "can_be_answered_already_prompt_template = \"\"\"\n",
    "You receive a query: {question} and a context: {context}.\n",
    "You need to determine if the question can be fully answered relying only on the given context.\n",
    "The only information you have and can rely on is the context you received. \n",
    "You have no prior knowledge of the question or the context.\n",
    "If you think the question can be answered based on the context, output 'true', otherwise output 'false'.\n",
    "\"\"\"\n",
    "\n",
    "# Create the PromptTemplate object\n",
    "can_be_answered_already_prompt = PromptTemplate(\n",
    "    template=can_be_answered_already_prompt_template,\n",
    "    input_variables=[\"question\", \"context\"],\n",
    ")\n",
    "\n",
    "# Initialize the LLM for this task (using GPT-4o)\n",
    "can_be_answered_already_llm = ChatOpenAI(\n",
    "    temperature=0,\n",
    "    model_name=\"gpt-4o\",\n",
    "    max_tokens=2000\n",
    ")\n",
    "\n",
    "# Compose the chain: prompt -> LLM -> structured output\n",
    "can_be_answered_already_chain = (\n",
    "    can_be_answered_already_prompt\n",
    "    | can_be_answered_already_llm.with_structured_output(CanBeAnsweredAlready)\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Define the sophisticated pipeline graph functions"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "from pprint import pprint\n",
    "\n",
    "def run_task_handler_chain(state: PlanExecute):\n",
    "    \"\"\"\n",
    "    Run the task handler chain to decide which tool to use to execute the task.\n",
    "\n",
    "    Args:\n",
    "        state: The current state of the plan execution.\n",
    "\n",
    "    Returns:\n",
    "        The updated state of the plan execution.\n",
    "    \"\"\"\n",
    "    state[\"curr_state\"] = \"task_handler\"\n",
    "    print(\"the current plan is:\")\n",
    "    print(state[\"plan\"])\n",
    "    pprint(\"--------------------\") \n",
    "\n",
    "    # Initialize past_steps if not present\n",
    "    if not state['past_steps']:\n",
    "        state[\"past_steps\"] = []\n",
    "\n",
    "    # Get the current task from the plan\n",
    "    curr_task = state[\"plan\"][0]\n",
    "\n",
    "    # Prepare inputs for the task handler chain\n",
    "    inputs = {\n",
    "        \"curr_task\": curr_task,\n",
    "        \"aggregated_context\": state[\"aggregated_context\"],\n",
    "        \"last_tool\": state[\"tool\"],\n",
    "        \"past_steps\": state[\"past_steps\"],\n",
    "        \"question\": state[\"question\"]\n",
    "    }\n",
    "    \n",
    "    # Invoke the task handler chain\n",
    "    output = task_handler_chain.invoke(inputs)\n",
    "  \n",
    "    # Update state with the completed task\n",
    "    state[\"past_steps\"].append(curr_task)\n",
    "    state[\"plan\"].pop(0)\n",
    "\n",
    "    # Decide which tool to use based on output\n",
    "    if output.tool == \"retrieve_chunks\":\n",
    "        state[\"query_to_retrieve_or_answer\"] = output.query\n",
    "        state[\"tool\"] = \"retrieve_chunks\"\n",
    "    elif output.tool == \"retrieve_summaries\":\n",
    "        state[\"query_to_retrieve_or_answer\"] = output.query\n",
    "        state[\"tool\"] = \"retrieve_summaries\"\n",
    "    elif output.tool == \"retrieve_quotes\":\n",
    "        state[\"query_to_retrieve_or_answer\"] = output.query\n",
    "        state[\"tool\"] = \"retrieve_quotes\"\n",
    "    elif output.tool == \"answer_from_context\":\n",
    "        state[\"query_to_retrieve_or_answer\"] = output.query\n",
    "        state[\"curr_context\"] = output.curr_context\n",
    "        state[\"tool\"] = \"answer\"\n",
    "    else:\n",
    "        raise ValueError(\"Invalid tool was outputed. Must be either 'retrieve' or 'answer_from_context'\")\n",
    "    return state  \n",
    "\n",
    "\n",
    "def retrieve_or_answer(state: PlanExecute):\n",
    "    \"\"\"\n",
    "    Decide whether to retrieve or answer the question based on the current state.\n",
    "\n",
    "    Args:\n",
    "        state: The current state of the plan execution.\n",
    "\n",
    "    Returns:\n",
    "        String indicating the chosen tool.\n",
    "    \"\"\"\n",
    "    state[\"curr_state\"] = \"decide_tool\"\n",
    "    print(\"deciding whether to retrieve or answer\")\n",
    "    if state[\"tool\"] == \"retrieve_chunks\":\n",
    "        return \"chosen_tool_is_retrieve_chunks\"\n",
    "    elif state[\"tool\"] == \"retrieve_summaries\":\n",
    "        return \"chosen_tool_is_retrieve_summaries\"\n",
    "    elif state[\"tool\"] == \"retrieve_quotes\":\n",
    "        return \"chosen_tool_is_retrieve_quotes\"\n",
    "    elif state[\"tool\"] == \"answer\":\n",
    "        return \"chosen_tool_is_answer\"\n",
    "    else:\n",
    "        raise ValueError(\"Invalid tool was outputed. Must be either 'retrieve' or 'answer_from_context'\")  \n",
    "\n",
    "\n",
    "def run_qualitative_chunks_retrieval_workflow(state):\n",
    "    \"\"\"\n",
    "    Run the qualitative chunks retrieval workflow.\n",
    "\n",
    "    Args:\n",
    "        state: The current state of the plan execution.\n",
    "\n",
    "    Returns:\n",
    "        The state with the updated aggregated context.\n",
    "    \"\"\"\n",
    "    state[\"curr_state\"] = \"retrieve_chunks\"\n",
    "    print(\"Running the qualitative chunks retrieval workflow...\")\n",
    "    question = state[\"query_to_retrieve_or_answer\"]\n",
    "    inputs = {\"question\": question}\n",
    "    # Stream outputs from the workflow app\n",
    "    for output in qualitative_chunks_retrieval_workflow_app.stream(inputs):\n",
    "        for _, _ in output.items():\n",
    "            pass \n",
    "        pprint(\"--------------------\")\n",
    "    # Aggregate the retrieved context\n",
    "    if not state[\"aggregated_context\"]:\n",
    "        state[\"aggregated_context\"] = \"\"\n",
    "    state[\"aggregated_context\"] += output['relevant_context']\n",
    "    return state\n",
    "\n",
    "\n",
    "def run_qualitative_summaries_retrieval_workflow(state):\n",
    "    \"\"\"\n",
    "    Run the qualitative summaries retrieval workflow.\n",
    "\n",
    "    Args:\n",
    "        state: The current state of the plan execution.\n",
    "\n",
    "    Returns:\n",
    "        The state with the updated aggregated context.\n",
    "    \"\"\"\n",
    "    state[\"curr_state\"] = \"retrieve_summaries\"\n",
    "    print(\"Running the qualitative summaries retrieval workflow...\")\n",
    "    question = state[\"query_to_retrieve_or_answer\"]\n",
    "    inputs = {\"question\": question}\n",
    "    for output in qualitative_summaries_retrieval_workflow_app.stream(inputs):\n",
    "        for _, _ in output.items():\n",
    "            pass \n",
    "        pprint(\"--------------------\")\n",
    "    if not state[\"aggregated_context\"]:\n",
    "        state[\"aggregated_context\"] = \"\"\n",
    "    state[\"aggregated_context\"] += output['relevant_context']\n",
    "    return state\n",
    "\n",
    "\n",
    "def run_qualitative_book_quotes_retrieval_workflow(state):\n",
    "    \"\"\"\n",
    "    Run the qualitative book quotes retrieval workflow.\n",
    "\n",
    "    Args:\n",
    "        state: The current state of the plan execution.\n",
    "\n",
    "    Returns:\n",
    "        The state with the updated aggregated context.\n",
    "    \"\"\"\n",
    "    state[\"curr_state\"] = \"retrieve_book_quotes\"\n",
    "    print(\"Running the qualitative book quotes retrieval workflow...\")\n",
    "    question = state[\"query_to_retrieve_or_answer\"]\n",
    "    inputs = {\"question\": question}\n",
    "    for output in qualitative_book_quotes_retrieval_workflow_app.stream(inputs):\n",
    "        for _, _ in output.items():\n",
    "            pass \n",
    "        pprint(\"--------------------\")\n",
    "    if not state[\"aggregated_context\"]:\n",
    "        state[\"aggregated_context\"] = \"\"\n",
    "    state[\"aggregated_context\"] += output['relevant_context']\n",
    "    return state\n",
    "   \n",
    "\n",
    "def run_qualtative_answer_workflow(state):\n",
    "    \"\"\"\n",
    "    Run the qualitative answer workflow.\n",
    "\n",
    "    Args:\n",
    "        state: The current state of the plan execution.\n",
    "\n",
    "    Returns:\n",
    "        The state with the updated aggregated context.\n",
    "    \"\"\"\n",
    "    state[\"curr_state\"] = \"answer\"\n",
    "    print(\"Running the qualitative answer workflow...\")\n",
    "    question = state[\"query_to_retrieve_or_answer\"]\n",
    "    context = state[\"curr_context\"]\n",
    "    inputs = {\"question\": question, \"context\": context}\n",
    "    for output in qualitative_answer_workflow_app.stream(inputs):\n",
    "        for _, _ in output.items():\n",
    "            pass \n",
    "        pprint(\"--------------------\")\n",
    "    if not state[\"aggregated_context\"]:\n",
    "        state[\"aggregated_context\"] = \"\"\n",
    "    state[\"aggregated_context\"] += output[\"answer\"]\n",
    "    return state\n",
    "\n",
    "\n",
    "def run_qualtative_answer_workflow_for_final_answer(state):\n",
    "    \"\"\"\n",
    "    Run the qualitative answer workflow for the final answer.\n",
    "\n",
    "    Args:\n",
    "        state: The current state of the plan execution.\n",
    "\n",
    "    Returns:\n",
    "        The state with the updated response.\n",
    "    \"\"\"\n",
    "    state[\"curr_state\"] = \"get_final_answer\"\n",
    "    print(\"Running the qualitative answer workflow for final answer...\")\n",
    "    question = state[\"question\"]\n",
    "    context = state[\"aggregated_context\"]\n",
    "    inputs = {\"question\": question, \"context\": context}\n",
    "    for output in qualitative_answer_workflow_app.stream(inputs):\n",
    "        for _, value in output.items():\n",
    "            pass  \n",
    "        pprint(\"--------------------\")\n",
    "    state[\"response\"] = value\n",
    "    return state\n",
    "\n",
    "\n",
    "def anonymize_queries(state: PlanExecute):\n",
    "    \"\"\"\n",
    "    Anonymizes the question.\n",
    "\n",
    "    Args:\n",
    "        state: The current state of the plan execution.\n",
    "\n",
    "    Returns:\n",
    "        The updated state with the anonymized question and mapping.\n",
    "    \"\"\"\n",
    "    state[\"curr_state\"] = \"anonymize_question\"\n",
    "    print(\"Anonymizing question\")\n",
    "    pprint(\"--------------------\")\n",
    "    anonymized_question_output = anonymize_question_chain.invoke(state['question'])\n",
    "    anonymized_question = anonymized_question_output[\"anonymized_question\"]\n",
    "    print(f'anonimized_querry: {anonymized_question}')\n",
    "    pprint(\"--------------------\")\n",
    "    mapping = anonymized_question_output[\"mapping\"]\n",
    "    state[\"anonymized_question\"] = anonymized_question\n",
    "    state[\"mapping\"] = mapping\n",
    "    return state\n",
    "\n",
    "\n",
    "def deanonymize_queries(state: PlanExecute):\n",
    "    \"\"\"\n",
    "    De-anonymizes the plan.\n",
    "\n",
    "    Args:\n",
    "        state: The current state of the plan execution.\n",
    "\n",
    "    Returns:\n",
    "        The updated state with the de-anonymized plan.\n",
    "    \"\"\"\n",
    "    state[\"curr_state\"] = \"de_anonymize_plan\"\n",
    "    print(\"De-anonymizing plan\")\n",
    "    pprint(\"--------------------\")\n",
    "    deanonimzed_plan = de_anonymize_plan_chain.invoke({\"plan\": state[\"plan\"], \"mapping\": state[\"mapping\"]})\n",
    "    state[\"plan\"] = deanonimzed_plan.plan\n",
    "    print(f'de-anonimized_plan: {deanonimzed_plan.plan}')\n",
    "    return state\n",
    "\n",
    "\n",
    "def plan_step(state: PlanExecute):\n",
    "    \"\"\"\n",
    "    Plans the next step.\n",
    "\n",
    "    Args:\n",
    "        state: The current state of the plan execution.\n",
    "\n",
    "    Returns:\n",
    "        The updated state with the plan.\n",
    "    \"\"\"\n",
    "    state[\"curr_state\"] = \"planner\"\n",
    "    print(\"Planning step\")\n",
    "    pprint(\"--------------------\")\n",
    "    plan = planner.invoke({\"question\": state['anonymized_question']})\n",
    "    state[\"plan\"] = plan.steps\n",
    "    print(f'plan: {state[\"plan\"]}')\n",
    "    return state\n",
    "\n",
    "\n",
    "def break_down_plan_step(state: PlanExecute):\n",
    "    \"\"\"\n",
    "    Breaks down the plan steps into retrievable or answerable tasks.\n",
    "\n",
    "    Args:\n",
    "        state: The current state of the plan execution.\n",
    "\n",
    "    Returns:\n",
    "        The updated state with the refined plan.\n",
    "    \"\"\"\n",
    "    state[\"curr_state\"] = \"break_down_plan\"\n",
    "    print(\"Breaking down plan steps into retrievable or answerable tasks\")\n",
    "    pprint(\"--------------------\")\n",
    "    refined_plan = break_down_plan_chain.invoke(state[\"plan\"])\n",
    "    state[\"plan\"] = refined_plan.steps\n",
    "    return state\n",
    "\n",
    "\n",
    "def replan_step(state: PlanExecute):\n",
    "    \"\"\"\n",
    "    Replans the next step.\n",
    "\n",
    "    Args:\n",
    "        state: The current state of the plan execution.\n",
    "\n",
    "    Returns:\n",
    "        The updated state with the plan.\n",
    "    \"\"\"\n",
    "    state[\"curr_state\"] = \"replan\"\n",
    "    print(\"Replanning step\")\n",
    "    pprint(\"--------------------\")\n",
    "    inputs = {\n",
    "        \"question\": state[\"question\"],\n",
    "        \"plan\": state[\"plan\"],\n",
    "        \"past_steps\": state[\"past_steps\"],\n",
    "        \"aggregated_context\": state[\"aggregated_context\"]\n",
    "    }\n",
    "    output = replanner.invoke(inputs)\n",
    "    state[\"plan\"] = output['plan']['steps']\n",
    "    return state\n",
    "\n",
    "\n",
    "def can_be_answered(state: PlanExecute):\n",
    "    \"\"\"\n",
    "    Determines if the question can be answered.\n",
    "\n",
    "    Args:\n",
    "        state: The current state of the plan execution.\n",
    "\n",
    "    Returns:\n",
    "        String indicating whether the original question can be answered or not.\n",
    "    \"\"\"\n",
    "    state[\"curr_state\"] = \"can_be_answered_already\"\n",
    "    print(\"Checking if the ORIGINAL QUESTION can be answered already\")\n",
    "    pprint(\"--------------------\")\n",
    "    question = state[\"question\"]\n",
    "    context = state[\"aggregated_context\"]\n",
    "    inputs = {\"question\": question, \"context\": context}\n",
    "    output = can_be_answered_already_chain.invoke(inputs)\n",
    "    if output.can_be_answered == True:\n",
    "        print(\"The ORIGINAL QUESTION can be fully answered already.\")\n",
    "        pprint(\"--------------------\")\n",
    "        print(\"the aggregated context is:\")\n",
    "        print(text_wrap(state[\"aggregated_context\"]))\n",
    "        print(\"--------------------\")\n",
    "        return \"can_be_answered_already\"\n",
    "    else:\n",
    "        print(\"The ORIGINAL QUESTION cannot be fully answered yet.\")\n",
    "        pprint(\"--------------------\")\n",
    "        return \"cannot_be_answered_yet\""
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Define the sophisticated graph structure"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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",
      "text/plain": [
       "<IPython.core.display.Image object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "from langgraph.graph import StateGraph\n",
    "\n",
    "# -----------------------------------------------------------\n",
    "# Define the Plan-and-Execute Agent Workflow Graph\n",
    "# -----------------------------------------------------------\n",
    "\n",
    "# Initialize the workflow graph with the PlanExecute state\n",
    "agent_workflow = StateGraph(PlanExecute)\n",
    "\n",
    "# -------------------------\n",
    "# Add Nodes (Steps/Functions)\n",
    "# -------------------------\n",
    "\n",
    "# 1. Anonymize the question (replace named entities with variables)\n",
    "agent_workflow.add_node(\"anonymize_question\", anonymize_queries)\n",
    "\n",
    "# 2. Generate a step-by-step plan for the anonymized question\n",
    "agent_workflow.add_node(\"planner\", plan_step)\n",
    "\n",
    "# 3. De-anonymize the plan (replace variables back with original entities)\n",
    "agent_workflow.add_node(\"de_anonymize_plan\", deanonymize_queries)\n",
    "\n",
    "# 4. Break down the plan into retrievable/answerable tasks\n",
    "agent_workflow.add_node(\"break_down_plan\", break_down_plan_step)\n",
    "\n",
    "# 5. Decide which tool to use for the current task\n",
    "agent_workflow.add_node(\"task_handler\", run_task_handler_chain)\n",
    "\n",
    "# 6. Retrieve relevant book chunks\n",
    "agent_workflow.add_node(\"retrieve_chunks\", run_qualitative_chunks_retrieval_workflow)\n",
    "\n",
    "# 7. Retrieve relevant chapter summaries\n",
    "agent_workflow.add_node(\"retrieve_summaries\", run_qualitative_summaries_retrieval_workflow)\n",
    "\n",
    "# 8. Retrieve relevant book quotes\n",
    "agent_workflow.add_node(\"retrieve_book_quotes\", run_qualitative_book_quotes_retrieval_workflow)\n",
    "\n",
    "# 9. Answer the question from the aggregated context\n",
    "agent_workflow.add_node(\"answer\", run_qualtative_answer_workflow)\n",
    "\n",
    "# 10. Replan if needed (update plan based on progress/context)\n",
    "agent_workflow.add_node(\"replan\", replan_step)\n",
    "\n",
    "# 11. Get the final answer from the aggregated context\n",
    "agent_workflow.add_node(\"get_final_answer\", run_qualtative_answer_workflow_for_final_answer)\n",
    "\n",
    "# -------------------------\n",
    "# Define Workflow Edges (Transitions)\n",
    "# -------------------------\n",
    "\n",
    "# Set the entry point of the workflow\n",
    "agent_workflow.set_entry_point(\"anonymize_question\")\n",
    "\n",
    "# Anonymize -> Plan\n",
    "agent_workflow.add_edge(\"anonymize_question\", \"planner\")\n",
    "\n",
    "# Plan -> De-anonymize\n",
    "agent_workflow.add_edge(\"planner\", \"de_anonymize_plan\")\n",
    "\n",
    "# De-anonymize -> Break down plan\n",
    "agent_workflow.add_edge(\"de_anonymize_plan\", \"break_down_plan\")\n",
    "\n",
    "# Break down plan -> Task handler\n",
    "agent_workflow.add_edge(\"break_down_plan\", \"task_handler\")\n",
    "\n",
    "# Task handler -> (conditional) Retrieve or Answer\n",
    "agent_workflow.add_conditional_edges(\n",
    "    \"task_handler\",\n",
    "    retrieve_or_answer,\n",
    "    {\n",
    "        \"chosen_tool_is_retrieve_chunks\": \"retrieve_chunks\",\n",
    "        \"chosen_tool_is_retrieve_summaries\": \"retrieve_summaries\",\n",
    "        \"chosen_tool_is_retrieve_quotes\": \"retrieve_book_quotes\",\n",
    "        \"chosen_tool_is_answer\": \"answer\"\n",
    "    }\n",
    ")\n",
    "\n",
    "# Retrieval/Answer nodes -> Replan\n",
    "agent_workflow.add_edge(\"retrieve_chunks\", \"replan\")\n",
    "agent_workflow.add_edge(\"retrieve_summaries\", \"replan\")\n",
    "agent_workflow.add_edge(\"retrieve_book_quotes\", \"replan\")\n",
    "agent_workflow.add_edge(\"answer\", \"replan\")\n",
    "\n",
    "# Replan -> (conditional) Get final answer or continue\n",
    "agent_workflow.add_conditional_edges(\n",
    "    \"replan\",\n",
    "    can_be_answered,\n",
    "    {\n",
    "        \"can_be_answered_already\": \"get_final_answer\",\n",
    "        \"cannot_be_answered_yet\": \"break_down_plan\"\n",
    "    }\n",
    ")\n",
    "\n",
    "# Get final answer -> End\n",
    "agent_workflow.add_edge(\"get_final_answer\", END)\n",
    "\n",
    "# -------------------------\n",
    "# Compile and Visualize the Workflow\n",
    "# -------------------------\n",
    "\n",
    "plan_and_execute_app = agent_workflow.compile()\n",
    "\n",
    "# Display the workflow graph as a Mermaid diagram\n",
    "display(Image(plan_and_execute_app.get_graph(xray=True).draw_mermaid_png()))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "---\n",
      "config:\n",
      "  flowchart:\n",
      "    curve: linear\n",
      "---\n",
      "graph TD;\n",
      "\t__start__([<p>__start__</p>]):::first\n",
      "\tanonymize_question(anonymize_question)\n",
      "\tplanner(planner)\n",
      "\tde_anonymize_plan(de_anonymize_plan)\n",
      "\tbreak_down_plan(break_down_plan)\n",
      "\ttask_handler(task_handler)\n",
      "\tretrieve_chunks(retrieve_chunks)\n",
      "\tretrieve_summaries(retrieve_summaries)\n",
      "\tretrieve_book_quotes(retrieve_book_quotes)\n",
      "\tanswer(answer)\n",
      "\treplan(replan)\n",
      "\tget_final_answer(get_final_answer)\n",
      "\t__end__([<p>__end__</p>]):::last\n",
      "\t__start__ --> anonymize_question;\n",
      "\tanonymize_question --> planner;\n",
      "\tanswer --> replan;\n",
      "\tbreak_down_plan --> task_handler;\n",
      "\tde_anonymize_plan --> break_down_plan;\n",
      "\tplanner --> de_anonymize_plan;\n",
      "\treplan -. &nbsp;cannot_be_answered_yet&nbsp; .-> break_down_plan;\n",
      "\treplan -. &nbsp;can_be_answered_already&nbsp; .-> get_final_answer;\n",
      "\tretrieve_book_quotes --> replan;\n",
      "\tretrieve_chunks --> replan;\n",
      "\tretrieve_summaries --> replan;\n",
      "\ttask_handler -. &nbsp;chosen_tool_is_answer&nbsp; .-> answer;\n",
      "\ttask_handler -. &nbsp;chosen_tool_is_retrieve_quotes&nbsp; .-> retrieve_book_quotes;\n",
      "\ttask_handler -. &nbsp;chosen_tool_is_retrieve_chunks&nbsp; .-> retrieve_chunks;\n",
      "\ttask_handler -. &nbsp;chosen_tool_is_retrieve_summaries&nbsp; .-> retrieve_summaries;\n",
      "\tget_final_answer --> __end__;\n",
      "\tclassDef default fill:#f2f0ff,line-height:1.2\n",
      "\tclassDef first fill-opacity:0\n",
      "\tclassDef last fill:#bfb6fc\n",
      "\n"
     ]
    }
   ],
   "source": [
    "print(plan_and_execute_app.get_graph().draw_mermaid())"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Run the sophisticated graph function"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "def execute_plan_and_print_steps(inputs, recursion_limit=45):\n",
    "    \"\"\"\n",
    "    Executes the plan-and-execute agent workflow and prints each step.\n",
    "\n",
    "    Args:\n",
    "        inputs (dict): The initial input state for the plan-and-execute agent.\n",
    "        recursion_limit (int): Maximum number of steps to prevent infinite loops.\n",
    "\n",
    "    Returns:\n",
    "        tuple: (response, final_state)\n",
    "            response (str): The final answer or message if not found.\n",
    "            final_state (dict): The final state after execution.\n",
    "    \"\"\"\n",
    "    # Configuration for the workflow (limits recursion to avoid infinite loops)\n",
    "    config = {\"recursion_limit\": recursion_limit}\n",
    "    try:\n",
    "        # Stream the outputs from the plan_and_execute_app workflow\n",
    "        for plan_output in plan_and_execute_app.stream(inputs, config=config):\n",
    "            # Iterate through each step's output and print the current state\n",
    "            for _, agent_state_value in plan_output.items():\n",
    "                pass  # agent_state_value holds the latest state after each node execution\n",
    "                print(f' curr step: {agent_state_value}')\n",
    "        # Extract the final response from the last state\n",
    "        response = agent_state_value['response']\n",
    "    except langgraph.pregel.GraphRecursionError:\n",
    "        # Handle the case where the recursion limit is reached\n",
    "        response = \"The answer wasn't found in the data.\"\n",
    "    # Save the final state for further inspection or evaluation\n",
    "    final_state = agent_state_value\n",
    "    # Print the final answer in a wrapped format for readability\n",
    "    print(text_wrap(f' the final answer is: {response}'))\n",
    "    return response, final_state"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Examples"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### An example we want the model to fail"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# -----------------------------------------------------------\n",
    "# Example: Run the Plan-and-Execute Agent for a Sample Question\n",
    "# -----------------------------------------------------------\n",
    "\n",
    "# Define the input question for the agent\n",
    "input = {\n",
    "    \"question\": \"what did professor lupin teach?\"\n",
    "}\n",
    "\n",
    "# Execute the plan-and-execute workflow and print each step\n",
    "final_answer, final_state = execute_plan_and_print_steps(input)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### An example we want the model to succeed"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# -----------------------------------------------------------\n",
    "# Example: Run the Plan-and-Execute Agent for a Complex Question\n",
    "# -----------------------------------------------------------\n",
    "\n",
    "# Define the input question for the agent.\n",
    "# This question requires reasoning about the professor who helped the villain and what class they teach.\n",
    "input = {\n",
    "    \"question\": \"what is the class that the proffessor who helped the villain is teaching?\"\n",
    "}\n",
    "\n",
    "# Execute the plan-and-execute workflow and print each step.\n",
    "# The function will print the reasoning process and the final answer.\n",
    "final_answer, final_state = execute_plan_and_print_steps(input)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### An example that demonstrates the CoT reasoning, when answering a question"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# -----------------------------------------------------------\n",
    "# Example: Run the Plan-and-Execute Agent for a Reasoning Question\n",
    "# -----------------------------------------------------------\n",
    "\n",
    "# Define the input question for the agent.\n",
    "# This question requires reasoning about how Harry defeated Quirrell.\n",
    "input = {\n",
    "    \"question\": \"how did harry beat quirrell?\"\n",
    "}\n",
    "\n",
    "# Execute the plan-and-execute workflow and print each step.\n",
    "# The function will print the reasoning process and the final answer.\n",
    "final_answer, final_state = execute_plan_and_print_steps(input)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "JBKQkR-W4ZyV"
   },
   "source": [
    "### Model Evaluation\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "id": "ME52zvjPNv47"
   },
   "outputs": [],
   "source": [
    "# -----------------------------------------------------------\n",
    "# Define Evaluation Questions and Ground Truth Answers\n",
    "# -----------------------------------------------------------\n",
    "\n",
    "# List of evaluation questions for the Harry Potter RAG pipeline.\n",
    "questions = [\n",
    "    \"What is the name of the three-headed dog guarding the Sorcerer's Stone?\",\n",
    "    \"Who gave Harry Potter his first broomstick?\",\n",
    "    \"Which house did the Sorting Hat initially consider for Harry?\",\n",
    "    # \"What is the name of Harry's owl?\",\n",
    "    # \"How did Harry and his friends get past Fluffy?\",\n",
    "    # \"What is the Mirror of Erised?\",\n",
    "    # \"Who tried to steal the Sorcerer's Stone?\",\n",
    "    # \"How did Harry defeat Quirrell?\",\n",
    "    # \"What is Harry's parent's secret weapon against Voldemort?\",\n",
    "]\n",
    "\n",
    "# Corresponding ground truth answers for the evaluation questions.\n",
    "ground_truth_answers = [\n",
    "    \"Fluffy\",\n",
    "    \"Professor McGonagall\",\n",
    "    \"Slytherin\",\n",
    "    # \"Hedwig\",\n",
    "    # \"They played music to put Fluffy to sleep.\",\n",
    "    # \"A magical mirror that shows the 'deepest, most desperate desire of our hearts.'\",\n",
    "    # \"Professor Quirrell, possessed by Voldemort\",\n",
    "    # \"Harry's mother's love protected him, causing Quirrell/Voldemort pain when they touched him.\",\n",
    "]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Generating Answers and Retrieving Documents for Predefined Questions\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 460
    },
    "id": "Wo9EEV0j4mJA",
    "outputId": "14c46214-8fb8-41aa-9845-73367d9a738f"
   },
   "outputs": [],
   "source": [
    "# -----------------------------------------------------------\n",
    "# Generate Answers and Retrieve Documents for Evaluation Questions\n",
    "# -----------------------------------------------------------\n",
    "\n",
    "generated_answers = []        # List to store the generated answers for each question\n",
    "retrieved_documents = []      # List to store the aggregated context (retrieved documents) for each question\n",
    "\n",
    "# Iterate over each evaluation question\n",
    "for question in questions:\n",
    "    # Prepare the input dictionary for the plan-and-execute pipeline\n",
    "    input = {\"question\": question}\n",
    "    print(f\"Answering the question: {question}\")\n",
    "\n",
    "    # Execute the plan-and-execute pipeline and obtain the final answer and state\n",
    "    final_answer, final_state = execute_plan_and_print_steps(input)\n",
    "\n",
    "    # Store the generated answer\n",
    "    generated_answers.append(final_answer)\n",
    "\n",
    "    # Store the aggregated context (retrieved documents) used to answer the question\n",
    "    retrieved_documents.append(final_state['aggregated_context'])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Displaying Retrieved Documents and Generated Answers\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# -----------------------------------------------------------\n",
    "# Display Retrieved Documents and Generated Answers\n",
    "# -----------------------------------------------------------\n",
    "\n",
    "# Print the retrieved documents for each evaluation question in a readable format\n",
    "print(text_wrap(f\"retrieved_documents: {retrieved_documents}\\n\"))\n",
    "\n",
    "# Print the generated answers for each evaluation question in a readable format\n",
    "print(text_wrap(f\"generated_answers: {generated_answers}\"))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Preparing Data and Conducting Ragas Evaluation\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "Evaluating: 100%|██████████| 15/15 [00:51<00:00,  3.44s/it]\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "                                            question                answer  \\\n",
      "0  What is the name of the three-headed dog guard...                Fluffy   \n",
      "1        Who gave Harry Potter his first broomstick?  Professor McGonagall   \n",
      "2  Which house did the Sorting Hat initially cons...             Slytherin   \n",
      "\n",
      "                                            contexts          ground_truth  \\\n",
      "0  [I, n,  , C, h, a, p, t, e, r,  , S, i, x, t, ...                Fluffy   \n",
      "1  [I, n,  , C, h, a, p, t, e, r,  , E, i, g, h, ...  Professor McGonagall   \n",
      "2  [T, h, e,  , S, o, r, t, i, n, g,  , H, a, t, ...             Slytherin   \n",
      "\n",
      "   answer_correctness  faithfulness  answer_relevancy  context_recall  \\\n",
      "0                 1.0           1.0          1.000000             1.0   \n",
      "1                 1.0           1.0          0.946824             1.0   \n",
      "2                 1.0           0.0          0.889830             0.0   \n",
      "\n",
      "   answer_similarity  \n",
      "0                1.0  \n",
      "1                1.0  \n",
      "2                1.0  \n"
     ]
    }
   ],
   "source": [
    "# -----------------------------------------------------------\n",
    "# Prepare Data and Conduct Ragas Evaluation\n",
    "# -----------------------------------------------------------\n",
    "\n",
    "# 1. Prepare the data dictionary for Ragas evaluation\n",
    "data_samples = {\n",
    "    'question': questions,                # List of evaluation questions\n",
    "    'answer': generated_answers,          # List of generated answers from the pipeline\n",
    "    'contexts': retrieved_documents,      # List of aggregated/retrieved contexts for each question\n",
    "    'ground_truth': ground_truth_answers  # List of ground truth answers for evaluation\n",
    "}\n",
    "\n",
    "# 2. Ensure each context is a list of strings (required by Ragas)\n",
    "#    If each context is a single string, wrap it in a list.\n",
    "data_samples['contexts'] = [[context] if isinstance(context, str) else context for context in data_samples['contexts']]\n",
    "\n",
    "# 3. Create a HuggingFace Dataset from the data dictionary\n",
    "dataset = Dataset.from_dict(data_samples)\n",
    "\n",
    "# 4. Define the Ragas evaluation metrics to use\n",
    "metrics = [\n",
    "    answer_correctness,\n",
    "    faithfulness,\n",
    "    answer_relevancy,\n",
    "    context_recall,\n",
    "    answer_similarity\n",
    "]\n",
    "\n",
    "# 5. Initialize the LLM for Ragas evaluation (using GPT-4o)\n",
    "llm = ChatOpenAI(temperature=0, model_name=\"gpt-4o\", max_tokens=4000)\n",
    "\n",
    "# 6. Run the Ragas evaluation on the dataset with the specified metrics\n",
    "score = evaluate(dataset, metrics=metrics, llm=llm)\n",
    " \n",
    "# 7. Convert the results to a pandas DataFrame and print\n",
    "results_df = score.to_pandas()\n",
    "print(results_df)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Analyzing Metric Results from Ragas Evaluation\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "**QUESTION**\n",
      "\n",
      "**ANSWER**\n",
      "\n",
      "**CONTEXTS**\n",
      "\n",
      "**GROUND_TRUTH**\n",
      "\n",
      "**ANSWER_CORRECTNESS**\n",
      "Measures whether the generated answer is factually correct.\n",
      "Score: 1.0000\n",
      "\n",
      "**FAITHFULNESS**\n",
      "Measures how well the generated answer is supported by the retrieved documents.\n",
      "Score: 1.0000\n",
      "\n",
      "**ANSWER_RELEVANCY**\n",
      "Measures how relevant the generated answer is to the question.\n",
      "Score: 1.0000\n",
      "\n",
      "**CONTEXT_RECALL**\n",
      "Measures the proportion of relevant documents that are successfully retrieved.\n",
      "Score: 1.0000\n",
      "\n",
      "**ANSWER_SIMILARITY**\n",
      "Measures the semantic similarity between the generated answer and the ground truth answer.\n",
      "Score: 1.0000\n"
     ]
    }
   ],
   "source": [
    "# Call the function to analyze the metric results from the Ragas evaluation\n",
    "# 'results_df' is the DataFrame containing the evaluation metrics for each question\n",
    "analyse_metric_results(results_df)  # Analyse the results"
   ]
  }
 ],
 "metadata": {
  "colab": {
   "provenance": []
  },
  "kernelspec": {
   "display_name": ".venv-cccccccccccccccasffasfasf",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.0"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 0
}
